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/interfaces/xoverlay.h>
40 #include <mm_attrs_private.h>
43 #include "mm_player_priv.h"
44 #include "mm_player_ini.h"
45 #include "mm_player_attrs.h"
46 #include "mm_player_capture.h"
47 #include "mm_player_utils.h"
52 #define MM_SMOOTH_STREAMING
54 /*===========================================================================================
56 | LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
58 ========================================================================================== */
60 /*---------------------------------------------------------------------------
61 | GLOBAL CONSTANT DEFINITIONS: |
62 ---------------------------------------------------------------------------*/
64 /*---------------------------------------------------------------------------
65 | IMPORTED VARIABLE DECLARATIONS: |
66 ---------------------------------------------------------------------------*/
68 /*---------------------------------------------------------------------------
69 | IMPORTED FUNCTION DECLARATIONS: |
70 ---------------------------------------------------------------------------*/
72 /*---------------------------------------------------------------------------
74 ---------------------------------------------------------------------------*/
75 #define TRICK_PLAY_MUTE_THRESHOLD_MAX 2.0
76 #define TRICK_PLAY_MUTE_THRESHOLD_MIN 0.0
78 #define MM_VOLUME_FACTOR_DEFAULT 1.0
79 #define MM_VOLUME_FACTOR_MIN 0
80 #define MM_VOLUME_FACTOR_MAX 1.0
82 #define MM_PLAYER_FADEOUT_TIME_DEFAULT 700000 // 700 msec
84 #define MM_PLAYER_MPEG_VNAME "mpegversion"
85 #define MM_PLAYER_DIVX_VNAME "divxversion"
86 #define MM_PLAYER_WMV_VNAME "wmvversion"
87 #define MM_PLAYER_WMA_VNAME "wmaversion"
89 #define DEFAULT_PLAYBACK_RATE 1.0
90 #define PLAYBACK_RATE_EX_AUDIO_MIN 0.5
91 #define PLAYBACK_RATE_EX_AUDIO_MAX 2.0
92 #define PLAYBACK_RATE_EX_VIDEO_MIN 0.5
93 #define PLAYBACK_RATE_EX_VIDEO_MAX 1.5
95 #define GST_QUEUE_DEFAULT_TIME 4
96 #define GST_QUEUE_HLS_TIME 8
98 #define DEFAULT_AUDIO_CH 0
100 /* video capture callback*/
101 gulong ahs_appsrc_cb_probe_id = 0;
103 #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) )
105 #define LAZY_PAUSE_TIMEOUT_MSEC 700
106 #define MM_PLAYER_NAME "mmplayer"
108 //#define ENABLE_DRMSRC
110 /*---------------------------------------------------------------------------
111 | LOCAL CONSTANT DEFINITIONS: |
112 ---------------------------------------------------------------------------*/
114 /*---------------------------------------------------------------------------
115 | LOCAL DATA TYPE DEFINITIONS: |
116 ---------------------------------------------------------------------------*/
118 /*---------------------------------------------------------------------------
119 | GLOBAL VARIABLE DEFINITIONS: |
120 ---------------------------------------------------------------------------*/
122 /*---------------------------------------------------------------------------
123 | LOCAL VARIABLE DEFINITIONS: |
124 ---------------------------------------------------------------------------*/
126 /*---------------------------------------------------------------------------
127 | LOCAL FUNCTION PROTOTYPES: |
128 ---------------------------------------------------------------------------*/
129 static int __mmplayer_set_state(mm_player_t* player, int state);
130 static int __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
131 static int __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
132 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player);
133 static int __mmplayer_gst_create_subtitle_src(mm_player_t* player);
134 static int __mmplayer_gst_create_pipeline(mm_player_t* player);
135 static int __mmplayer_gst_destroy_pipeline(mm_player_t* player);
136 static int __mmplayer_gst_element_link_bucket(GList* element_bucket);
138 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
139 static void __mmplayer_gst_selector_blocked(GstPad* pad, gboolean blocked, gpointer data);
140 static void __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
141 static void __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
142 static void __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
143 static void __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad* pad, GstCaps *caps, gpointer data);
144 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad* pad, GstCaps * caps, gpointer data);
145 static gint __mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
146 //static GValueArray* __mmplayer_gst_decode_autoplug_factories(GstElement *bin, GstPad* pad, GstCaps * caps, gpointer data);
147 static GValueArray* __mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad* pad, GstCaps * caps, GValueArray *factories, gpointer data);
148 static void __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad* new_pad, gpointer data);
149 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
150 static void __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
151 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
152 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
154 static void __mmplayer_typefind_have_type( GstElement *tf, guint probability, GstCaps *caps, gpointer data);
155 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
156 static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data);
157 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
158 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
159 static gboolean __mmplayer_is_omx_decoder_type(mm_player_t* player); // mp3
160 static void __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
161 //static void __mmplayer_check_video_zero_cpoy(mm_player_t* player, GstElementFactory* factory);
163 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
164 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
165 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
167 static void __mmplayer_gst_rtp_no_more_pads (GstElement *element, gpointer data);
168 static void __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
169 static void __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
170 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
171 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
174 static void __mmplayer_init_factories(mm_player_t* player);
175 static void __mmplayer_release_factories(mm_player_t* player);
176 static void __mmplayer_release_misc(mm_player_t* player);
177 static void __mmplayer_release_misc_post(mm_player_t* player);
178 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
180 static int __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline, GstState state, gboolean async, gint timeout );
181 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
182 static gboolean __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
184 int __mmplayer_switch_audio_sink (mm_player_t* player);
185 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
186 static int __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
187 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
188 static gboolean __mmplayer_video_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
189 static gboolean __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstBuffer *buffer, gpointer u_data);
190 static int __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index);
192 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
193 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
194 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
195 static gboolean __mmplayer_handle_streaming_error ( mm_player_t* player, GstMessage * message );
196 static void __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms );
197 static void __mmplayer_cancel_eos_timer( mm_player_t* player );
198 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
199 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
200 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
201 static int __mmplayer_handle_missed_plugin(mm_player_t* player);
202 static int __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
203 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
204 static void __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
205 static void __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
206 static void __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
207 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
208 static gpointer __mmplayer_next_play_thread(gpointer data);
209 static gpointer __mmplayer_repeat_thread(gpointer data);
210 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
213 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
214 static gboolean __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data);
215 static void __mmplayer_release_dump_list (GList *dump_list);
217 static int __gst_realize(mm_player_t* player);
218 static int __gst_unrealize(mm_player_t* player);
219 static int __gst_start(mm_player_t* player);
220 static int __gst_stop(mm_player_t* player);
221 static int __gst_pause(mm_player_t* player, gboolean async);
222 static int __gst_resume(mm_player_t* player, gboolean async);
223 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
224 GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
225 gint64 cur, GstSeekType stop_type, gint64 stop );
226 static int __gst_pending_seek ( mm_player_t* player );
228 static int __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
229 static int __gst_get_position(mm_player_t* player, int format, unsigned long *position);
230 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
231 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
232 static int __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
234 static gint __gst_handle_core_error( mm_player_t* player, int code );
235 static gint __gst_handle_library_error( mm_player_t* player, int code );
236 static gint __gst_handle_resource_error( mm_player_t* player, int code );
237 static gint __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
238 static gint __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
239 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
241 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
242 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
245 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
246 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
248 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
249 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
252 const gchar * __get_state_name ( int state );
253 static gboolean __is_streaming( mm_player_t* player );
254 static gboolean __is_rtsp_streaming( mm_player_t* player );
255 static gboolean __is_wfd_streaming( mm_player_t* player );
256 static gboolean __is_live_streaming ( mm_player_t* player );
257 static gboolean __is_http_streaming( mm_player_t* player );
258 static gboolean __is_http_live_streaming( mm_player_t* player );
259 static gboolean __is_dash_streaming( mm_player_t* player );
260 static gboolean __is_smooth_streaming( mm_player_t* player );
261 static gboolean __is_http_progressive_down(mm_player_t* player);
262 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
264 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
266 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
267 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
268 static int __mmplayer_start_streaming_ext(mm_player_t *player);
269 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
270 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
271 static void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id);
273 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
274 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
275 static void __mmplayer_check_pipeline(mm_player_t* player);
276 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
277 static void __mmplayer_deactivate_old_path(mm_player_t *player);
278 static int __mmplayer_ignore_current_external_display_mode(mm_player_t* player);
279 #if 0 // We'll need this in future.
280 static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name);
283 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
284 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
285 static gboolean __mmplayer_can_do_interrupt(mm_player_t *player);
287 /* device change post proc */
288 void __mmplayer_device_change_post_process(gpointer user);
289 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score);
290 void __mmplayer_inc_cb_score(mm_player_t* player);
291 void __mmplayer_post_proc_reset(mm_player_t* player);
292 void __mmplayer_device_change_trigger_post_process(mm_player_t* player);
293 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
296 /*===========================================================================================
298 | FUNCTION DEFINITIONS |
300 ========================================================================================== */
302 /* implementing player FSM */
303 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
305 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
307 MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
308 MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
309 // MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
310 // MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
312 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
314 //debug_log("incomming command : %d \n", command );
316 current_state = MMPLAYER_CURRENT_STATE(player);
317 pending_state = MMPLAYER_PENDING_STATE(player);
318 // target_state = MMPLAYER_TARGET_STATE(player);
319 // prev_state = MMPLAYER_PREV_STATE(player);
321 MMPLAYER_PRINT_STATE(player);
325 case MMPLAYER_COMMAND_CREATE:
327 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
329 if ( current_state == MM_PLAYER_STATE_NULL ||
330 current_state == MM_PLAYER_STATE_READY ||
331 current_state == MM_PLAYER_STATE_PAUSED ||
332 current_state == MM_PLAYER_STATE_PLAYING )
337 case MMPLAYER_COMMAND_DESTROY:
339 /* destroy can called anytime */
341 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
345 case MMPLAYER_COMMAND_REALIZE:
347 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
349 if ( pending_state != MM_PLAYER_STATE_NONE )
355 /* need ready state to realize */
356 if ( current_state == MM_PLAYER_STATE_READY )
359 if ( current_state != MM_PLAYER_STATE_NULL )
365 case MMPLAYER_COMMAND_UNREALIZE:
367 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
369 if ( current_state == MM_PLAYER_STATE_NULL )
374 case MMPLAYER_COMMAND_START:
376 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
378 if ( pending_state == MM_PLAYER_STATE_NONE )
380 if ( current_state == MM_PLAYER_STATE_PLAYING )
382 else if ( current_state != MM_PLAYER_STATE_READY &&
383 current_state != MM_PLAYER_STATE_PAUSED )
386 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
390 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
392 debug_log("player is going to paused state, just change the pending state as playing");
401 case MMPLAYER_COMMAND_STOP:
403 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
405 if ( current_state == MM_PLAYER_STATE_READY )
408 /* need playing/paused state to stop */
409 if ( current_state != MM_PLAYER_STATE_PLAYING &&
410 current_state != MM_PLAYER_STATE_PAUSED )
415 case MMPLAYER_COMMAND_PAUSE:
417 if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
420 if (player->doing_seek)
421 goto NOT_COMPLETED_SEEK;
423 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
425 if ( pending_state == MM_PLAYER_STATE_NONE )
427 if ( current_state == MM_PLAYER_STATE_PAUSED )
429 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
432 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
436 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
438 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
439 debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
447 case MMPLAYER_COMMAND_RESUME:
450 if (player->doing_seek)
451 goto NOT_COMPLETED_SEEK;
453 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
455 if ( pending_state == MM_PLAYER_STATE_NONE )
457 if ( current_state == MM_PLAYER_STATE_PLAYING )
459 else if ( current_state != MM_PLAYER_STATE_PAUSED )
462 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
466 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
468 debug_log("player is going to paused state, just change the pending state as playing");
480 player->cmd = command;
482 return MM_ERROR_NONE;
485 debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
486 MMPLAYER_STATE_GET_NAME(current_state), command);
487 return MM_ERROR_PLAYER_INVALID_STATE;
490 debug_warning("not completed seek");
491 return MM_ERROR_PLAYER_DOING_SEEK;
494 debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
495 return MM_ERROR_PLAYER_NO_OP;
498 debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
499 return MM_ERROR_PLAYER_NO_OP;
503 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element, GstState state, gboolean async, gint timeout) // @
505 GstState element_state = GST_STATE_VOID_PENDING;
506 GstState element_pending_state = GST_STATE_VOID_PENDING;
507 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
511 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
512 return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
514 debug_log("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
517 ret = gst_element_set_state(element, state);
519 if ( ret == GST_STATE_CHANGE_FAILURE )
521 debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
523 /* dump state of all element */
524 __mmplayer_dump_pipeline_state( player );
526 return MM_ERROR_PLAYER_INTERNAL;
529 /* return here so state transition to be done in async mode */
532 debug_log("async state transition. not waiting for state complete.\n");
533 return MM_ERROR_NONE;
536 /* wait for state transition */
537 ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
539 if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
541 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
542 GST_ELEMENT_NAME(element),
543 gst_element_state_get_name(state), timeout );
545 debug_error(" [%s] state : %s pending : %s \n",
546 GST_ELEMENT_NAME(element),
547 gst_element_state_get_name(element_state),
548 gst_element_state_get_name(element_pending_state) );
550 /* dump state of all element */
551 __mmplayer_dump_pipeline_state( player );
553 return MM_ERROR_PLAYER_INTERNAL;
556 debug_log("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
560 return MM_ERROR_NONE;
564 __mmplayer_videostream_cb(GstElement *element, void *data,
565 int width, int height, gpointer user_data) // @
567 mm_player_t* player = (mm_player_t*)user_data;
569 return_if_fail ( player );
573 if (player->is_drm_file)
575 MMMessageParamType msg_param = { 0, };
576 debug_warning("not supported in drm file");
577 msg_param.code = MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
578 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
580 else if ( !player->set_mode.media_packet_video_stream && player->video_stream_cb)
582 MMPlayerVideoStreamDataType stream;
584 /* clear stream data structure */
585 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
588 stream.length_total = width * height * 4; // for rgb 32bit
589 stream.height = height;
590 stream.width = width;
591 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
598 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
600 mm_player_t* player = (mm_player_t*)data;
602 return_if_fail ( player );
606 if (player->video_frame_render_error_cb )
610 int surface_type = 0;
611 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
612 switch (surface_type)
614 case MM_DISPLAY_SURFACE_X_EXT:
615 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
616 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
619 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
625 debug_error("could not get surface type");
630 debug_warning("video_frame_render_error_cb was not set");
637 __mmplayer_device_change_post_process(gpointer user)
639 mm_player_t* player = (mm_player_t*)user;
640 unsigned long position = 0;
641 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
642 MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
647 ! player->pipeline ||
648 ! player->pipeline->mainbin ||
649 ! player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
654 current_state = MMPLAYER_CURRENT_STATE(player);
655 pending_state = MMPLAYER_PENDING_STATE(player);
657 if (player->post_proc.need_pause_and_resume)
659 debug_log("pausing");
660 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
661 ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
662 gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
665 /* seek should be done within pause and resume */
666 if (player->post_proc.need_seek)
668 debug_log("seeking");
669 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position);
670 debug_log(">> seek to current position = %ld ms", position);
671 __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE);
674 if (player->post_proc.need_pause_and_resume)
676 debug_log("resuming");
677 if ((pending_state == MM_PLAYER_STATE_PLAYING) ||
678 ((pending_state == MM_PLAYER_STATE_NONE) && (current_state != MM_PLAYER_STATE_PAUSED)))
679 gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING);
683 if (player->post_proc.need_async)
685 debug_log("setting async");
686 debug_log(">> player->display_stat = %d", player->display_stat);
688 if ((player->display_stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) ||
689 (player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE))
691 g_object_set(G_OBJECT(player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "async", TRUE, NULL);
693 /* TODO : need some comment here */
694 else if (player->display_stat == MMPLAYER_DISPLAY_STATUS_NULL)
696 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
702 __mmplayer_post_proc_reset(player);
706 void __mmplayer_set_required_cb_score(mm_player_t* player, guint score)
708 return_if_fail(player);
709 player->post_proc.required_cb_score = score;
710 debug_log("set required score to : %d", score);
713 void __mmplayer_inc_cb_score(mm_player_t* player)
715 return_if_fail(player);
716 player->post_proc.cb_score++;
717 debug_log("post proc cb score increased to %d", player->post_proc.cb_score);
720 void __mmplayer_post_proc_reset(mm_player_t* player)
722 return_if_fail(player);
724 /* check if already triggered */
725 if (player->post_proc.id)
727 /* TODO : need to consider multiple main context. !!!! */
728 if (FALSE == g_source_remove(player->post_proc.id) )
730 debug_error("failed to remove exist post_proc item");
732 player->post_proc.id = 0;
735 memset(&player->post_proc, 0, sizeof(mm_player_post_proc_t));
737 /* set default required cb score 1 as only audio device has changed in this case.
738 if display status is changed with audio device, required cb score is set 2 in display status callback.
739 this logic bases on the assumption which audio device callback is called after calling display status callback. */
740 player->post_proc.required_cb_score = 1;
744 __mmplayer_device_change_trigger_post_process(mm_player_t* player)
746 return_if_fail(player);
749 if ( player->post_proc.cb_score < player->post_proc.required_cb_score )
751 /* wait for next turn */
752 debug_log("wait for next turn. required cb score : %d current score : %d\n",
753 player->post_proc.required_cb_score, player->post_proc.cb_score);
757 /* check if already triggered */
758 if (player->post_proc.id)
760 /* TODO : need to consider multiple main context. !!!! */
761 if (FALSE == g_source_remove(player->post_proc.id) )
763 debug_error("failed to remove exist post_proc item");
765 player->post_proc.id = 0;
768 player->post_proc.id = g_idle_add((GSourceFunc)__mmplayer_device_change_post_process, (gpointer)player);
771 /* NOTE : Sound module has different latency according to output device So,
772 * synchronization problem can be happened whenever device is changed.
773 * To avoid this issue, we do reset avsystem or seek as workaroud.
776 __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data)
779 mm_sound_device_type_e device_type;
780 mm_player_t* player = (mm_player_t*) user_data;
782 return_if_fail( player );
784 debug_warning("device_info_changed_cb is called, device_h[0x%x], changed_info_type[%d]\n", device_h, changed_info_type);
786 __mmplayer_inc_cb_score(player);
788 /* get device type with device_h*/
789 ret = mm_sound_get_device_type(device_h, &device_type);
791 debug_error("failed to mm_sound_get_device_type()\n");
794 /* do pause and resume only if video is playing */
795 if ( player->videodec_linked && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING )
799 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
800 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
801 case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
802 case MM_SOUND_DEVICE_TYPE_HDMI:
803 case MM_SOUND_DEVICE_TYPE_MIRRORING:
805 player->post_proc.need_pause_and_resume = TRUE;
810 debug_log("do nothing");
813 debug_warning("dispatched");
815 __mmplayer_device_change_trigger_post_process(player);
819 __mmplayer_display_status_cb(GstElement *element, MMPlayerDisplayStatus stat, gpointer data)
821 mm_player_t* player = (mm_player_t*)data;
822 return_if_fail ( player );
825 guint required_cb_score = 2;
827 __mmplayer_inc_cb_score(player);
828 __mmplayer_set_required_cb_score(player, required_cb_score);
830 if ((player->pipeline->textbin == NULL) ||
831 (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst == NULL) ||
832 (player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst == NULL) ||
833 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
835 debug_warning("text bin is not ready yet");
839 if (player->is_subtitle_force_drop == TRUE)
841 debug_warning("subtitle is dropping");
842 player->display_stat = stat;
846 if (stat != util_get_is_connected_external_display())
848 debug_warning("stat is wrong!! (%d from xvimagesink)", stat);
852 if ((stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) || (stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE))
854 MMMessageParamType msg = {0, };
855 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL);
856 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
857 debug_log("external display is ACTIVE");
860 msg.subtitle.duration = 0;
862 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
864 else if (stat == MMPLAYER_DISPLAY_STATUS_NULL)
866 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
867 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL); //If it is not ACTIVE...
868 debug_log("external display is NULL");
871 if (player->display_stat != stat)
873 player->display_stat = stat;
875 g_object_set(G_OBJECT(player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "async", FALSE, NULL);
876 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst), "async", FALSE, NULL);
878 /* setup post processing */
879 player->post_proc.need_async = TRUE;
880 player->post_proc.need_seek = TRUE;
881 player->post_proc.need_pause_and_resume = TRUE;
887 __mmplayer_device_change_trigger_post_process(player);
892 __mmplayer_external_resolution_cb(GstElement *element, int width, int height, gpointer data)
894 mm_player_t* player = (mm_player_t*)data;
895 return_if_fail ( player );
898 if ((player->pipeline->textbin == NULL) ||
899 (player->pipeline->textbin[MMPLAYER_T_RENDER].gst == NULL) ||
900 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
902 debug_warning("text bin is not ready yet");
906 if((width==0 || height==0) && util_get_is_connected_external_display()!=MMPLAYER_DISPLAY_STATUS_NULL)
908 debug_warning("stat is wrong!! skip setting external resolution to 0");
911 debug_log("set external width and height : %d * %d", width, height);
912 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "external-width", width, NULL);
913 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "external-height", height, NULL);
915 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-width", width, NULL);
916 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-height", height, NULL);
922 __mmplayer_hided_window_cb(GstElement *element, gboolean is_hided , gpointer data)
924 mm_player_t* player = (mm_player_t*)data;
925 return_if_fail ( player );
928 if ((player->pipeline->textbin == NULL) ||
929 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
931 debug_warning("text_xvimagesink is not ready yet");
934 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "hided-window", is_hided, NULL);
935 debug_log("update window-hide status : %d", is_hided);
941 __mmplayer_quick_panel_on_cb(GstElement *element, gboolean quick_panel_on , gpointer data)
943 mm_player_t* player = (mm_player_t*)data;
944 return_if_fail ( player );
947 if ((player->pipeline->textbin == NULL) ||
948 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
950 debug_warning("text_xvimagesink is not ready yet");
953 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "quick-panel-on", quick_panel_on, NULL);
954 debug_log("update quick panel status : %d", quick_panel_on);
960 __mmplayer_multiwindow_active_cb(GstElement *element, gboolean multiwindow_active , gpointer data)
962 mm_player_t* player = (mm_player_t*)data;
963 return_if_fail ( player );
965 if ((player->pipeline->textbin == NULL) ||
966 (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst == NULL))
970 if (player->last_multiwin_status != multiwindow_active)
972 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst), "multiwindow-active", multiwindow_active, NULL);
973 player->last_multiwin_status = multiwindow_active;
974 debug_log("update multiwindow-active status : %d", multiwindow_active);
979 /* This function should be called after the pipeline goes PAUSED or higher
982 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
984 static gboolean has_duration = FALSE;
985 static gboolean has_video_attrs = FALSE;
986 static gboolean has_audio_attrs = FALSE;
987 static gboolean has_bitrate = FALSE;
988 gboolean missing_only = FALSE;
989 gboolean all = FALSE;
991 GstFormat fmt = GST_FORMAT_TIME;
993 GstStructure* p = NULL;
994 MMHandleType attrs = 0;
996 gint stream_service_type = STREAMING_SERVICE_NONE;
1001 return_val_if_fail ( player, FALSE );
1003 /* check player state here */
1004 if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
1005 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
1007 /* give warning now only */
1008 debug_warning("be careful. content attributes may not available in this state ");
1011 /* get content attribute first */
1012 attrs = MMPLAYER_GET_ATTRS(player);
1015 debug_error("cannot get content attribute");
1019 /* get update flag */
1021 if ( flag & ATTR_MISSING_ONLY )
1023 missing_only = TRUE;
1024 debug_log("updating missed attr only");
1027 if ( flag & ATTR_ALL )
1030 has_duration = FALSE;
1031 has_video_attrs = FALSE;
1032 has_audio_attrs = FALSE;
1033 has_bitrate = FALSE;
1035 debug_log("updating all attrs");
1038 if ( missing_only && all )
1040 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
1041 missing_only = FALSE;
1044 if ( (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
1046 debug_log("try to update duration");
1047 has_duration = FALSE;
1049 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
1051 player->duration = dur_nsec;
1052 debug_warning("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
1055 /* try to get streaming service type */
1056 stream_service_type = __mmplayer_get_stream_service_type( player );
1057 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
1059 /* check duration is OK */
1060 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
1062 /* FIXIT : find another way to get duration here. */
1063 debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
1067 /*update duration */
1068 mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
1069 has_duration = TRUE;
1073 if ( (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
1075 /* update audio params
1076 NOTE : We need original audio params and it can be only obtained from src pad of audio
1077 decoder. Below code only valid when we are not using 'resampler' just before
1078 'audioconverter'. */
1080 debug_log("try to update audio attrs");
1081 has_audio_attrs = FALSE;
1083 if ( player->pipeline->audiobin &&
1084 player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1086 GstCaps *caps_a = NULL;
1088 gint samplerate = 0, channels = 0;
1090 pad = gst_element_get_static_pad(
1091 player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
1095 caps_a = gst_pad_get_negotiated_caps( pad );
1099 p = gst_caps_get_structure (caps_a, 0);
1101 mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
1103 gst_structure_get_int (p, "rate", &samplerate);
1104 mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
1106 gst_structure_get_int (p, "channels", &channels);
1107 mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
1109 secure_debug_log("samplerate : %d channels : %d", samplerate, channels);
1111 gst_caps_unref( caps_a );
1114 has_audio_attrs = TRUE;
1118 debug_warning("not ready to get audio caps");
1121 gst_object_unref( pad );
1125 debug_warning("failed to get pad from audiosink");
1130 if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
1132 debug_log("try to update video attrs");
1133 has_video_attrs = FALSE;
1135 if ( player->pipeline->videobin &&
1136 player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1138 GstCaps *caps_v = NULL;
1143 pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
1146 caps_v = gst_pad_get_negotiated_caps( pad );
1149 p = gst_caps_get_structure (caps_v, 0);
1150 gst_structure_get_int (p, "width", &width);
1151 mm_attrs_set_int_by_name(attrs, "content_video_width", width);
1153 gst_structure_get_int (p, "height", &height);
1154 mm_attrs_set_int_by_name(attrs, "content_video_height", height);
1156 gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
1158 secure_debug_log("width : %d height : %d", width, height );
1160 gst_caps_unref( caps_v );
1165 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
1166 secure_debug_log("fps : %d", tmpNu / tmpDe);
1169 has_video_attrs = TRUE;
1173 debug_log("no negitiated caps from videosink");
1175 gst_object_unref( pad );
1180 debug_log("no videosink sink pad");
1186 if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
1188 has_bitrate = FALSE;
1190 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
1191 if (player->duration)
1193 guint64 data_size = 0;
1195 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1197 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1199 if (stat(path, &sb) == 0)
1201 data_size = (guint64)sb.st_size;
1204 else if (MMPLAYER_IS_HTTP_STREAMING(player))
1206 data_size = player->http_content_size;
1208 debug_log("try to update bitrate : data_size = %lld", data_size);
1212 guint64 bitrate = 0;
1213 guint64 msec_dur = 0;
1215 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
1216 bitrate = data_size * 8 * 1000 / msec_dur;
1217 secure_debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
1218 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
1223 if (MMPLAYER_IS_RTSP_STREAMING(player))
1225 if(player->total_bitrate)
1227 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
1235 if ( mmf_attrs_commit ( attrs ) )
1237 debug_error("failed to update attributes\n");
1246 gint __mmplayer_get_stream_service_type( mm_player_t* player )
1248 gint streaming_type = STREAMING_SERVICE_NONE;
1252 return_val_if_fail ( player &&
1254 player->pipeline->mainbin &&
1255 player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
1258 /* streaming service type if streaming */
1259 if ( ! MMPLAYER_IS_STREAMING(player) )
1260 return STREAMING_SERVICE_NONE;
1262 if (MMPLAYER_IS_RTSP_STREAMING(player))
1264 /* get property from rtspsrc element */
1265 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst),
1266 "service_type", &streaming_type, NULL);
1268 else if (MMPLAYER_IS_HTTP_STREAMING(player))
1270 streaming_type = (player->duration == 0) ?
1271 STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
1274 switch ( streaming_type )
1276 case STREAMING_SERVICE_LIVE:
1277 debug_log("it's live streaming");
1279 case STREAMING_SERVICE_VOD:
1280 debug_log("it's vod streaming");
1282 case STREAMING_SERVICE_NONE:
1283 debug_error("should not get here");
1286 debug_error("should not get here");
1289 player->streaming_type = streaming_type;
1292 return streaming_type;
1296 /* this function sets the player state and also report
1297 * it to applicaton by calling callback function
1300 __mmplayer_set_state(mm_player_t* player, int state) // @
1302 MMMessageParamType msg = {0, };
1303 int asm_result = MM_ERROR_NONE;
1304 gboolean post_bos = FALSE;
1305 gboolean interrupted_by_asm = FALSE;
1306 int ret = MM_ERROR_NONE;
1308 return_val_if_fail ( player, FALSE );
1310 if ( MMPLAYER_CURRENT_STATE(player) == state )
1312 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
1313 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1317 /* update player states */
1318 MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
1319 MMPLAYER_CURRENT_STATE(player) = state;
1321 /* FIXIT : it's better to do like below code
1322 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
1323 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1324 and add more code to handling PENDING_STATE.
1326 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
1327 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
1330 MMPLAYER_PRINT_STATE(player);
1332 /* do some FSM stuffs before posting new state to application */
1333 interrupted_by_asm = player->sm.by_asm_cb;
1335 switch ( MMPLAYER_CURRENT_STATE(player) )
1337 case MM_PLAYER_STATE_NULL:
1338 case MM_PLAYER_STATE_READY:
1340 if (player->cmd == MMPLAYER_COMMAND_STOP)
1342 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE);
1343 if ( asm_result != MM_ERROR_NONE )
1345 debug_error("failed to set asm state to stop\n");
1346 return MM_ERROR_POLICY_INTERNAL;
1352 case MM_PLAYER_STATE_PAUSED:
1354 if ( ! player->sent_bos )
1357 #define MMPLAYER_MAX_SOUND_PRIORITY 3
1359 /* it's first time to update all content attrs. */
1360 _mmplayer_update_content_attrs( player, ATTR_ALL );
1361 /* set max sound priority to keep own sound and not to mute other's one */
1362 mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found);
1365 mm_attrs_get_int_by_name(player->attrs, "content_audio_found", &found);
1368 debug_log("set max audio priority");
1369 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "priority", MMPLAYER_MAX_SOUND_PRIORITY, NULL);
1375 /* add audio callback probe if condition is satisfied */
1376 if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction )
1378 __mmplayer_configure_audio_callback(player);
1379 /* FIXIT : handle return value */
1382 if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
1384 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE);
1387 debug_error("failed to set asm state to PAUSE\n");
1388 return MM_ERROR_POLICY_INTERNAL;
1394 case MM_PLAYER_STATE_PLAYING:
1396 /* try to get content metadata */
1397 if ( ! player->sent_bos )
1399 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
1400 * c-api since c-api doesn't use _start() anymore. It may not work propery with
1401 * legacy mmfw-player api */
1402 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
1405 if ( (player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME) )
1407 if (!player->sent_bos)
1409 __mmplayer_handle_missed_plugin ( player );
1412 /* update ASM state for video and streaming buffering */
1413 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE);
1414 if (asm_result != MM_ERROR_NONE)
1416 if (player->pipeline->videobin)
1418 MMMessageParamType msg = {0, };
1420 debug_error("failed to go ahead because of video conflict\n");
1422 msg.union_type = MM_MSG_UNION_CODE;
1423 msg.code = MM_ERROR_POLICY_INTERRUPTED;
1424 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
1426 _mmplayer_unrealize((MMHandleType)player);
1430 debug_error("failed to play by ASM error : 0x%X\n", asm_result);
1431 _mmplayer_pause((MMHandleType)player);
1435 return MM_ERROR_POLICY_INTERNAL;
1439 if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
1441 /* initialize because auto resume is done well. */
1442 player->resumed_by_rewind = FALSE;
1443 player->playback_rate = 1.0;
1446 if ( !player->sent_bos )
1448 /* check audio codec field is set or not
1449 * we can get it from typefinder or codec's caps.
1451 gchar *audio_codec = NULL;
1452 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
1454 /* The codec format can't be sent for audio only case like amr, mid etc.
1455 * Because, parser don't make related TAG.
1456 * So, if it's not set yet, fill it with found data.
1458 if ( ! audio_codec )
1460 if ( g_strrstr(player->type, "audio/midi"))
1462 audio_codec = g_strdup("MIDI");
1465 else if ( g_strrstr(player->type, "audio/x-amr"))
1467 audio_codec = g_strdup("AMR");
1469 else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
1471 audio_codec = g_strdup("AAC");
1475 audio_codec = g_strdup("unknown");
1477 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1479 MMPLAYER_FREEIF(audio_codec);
1480 mmf_attrs_commit(player->attrs);
1481 debug_log("set audio codec type with caps\n");
1489 case MM_PLAYER_STATE_NONE:
1491 debug_warning("invalid target state, there is nothing to do.\n");
1496 /* post message to application */
1497 if (MMPLAYER_TARGET_STATE(player) == state)
1499 /* fill the message with state of player */
1500 msg.state.previous = MMPLAYER_PREV_STATE(player);
1501 msg.state.current = MMPLAYER_CURRENT_STATE(player);
1503 debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
1505 /* state changed by asm callback */
1506 if ( interrupted_by_asm )
1508 msg.union_type = MM_MSG_UNION_CODE;
1509 msg.code = player->sm.event_src;
1510 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
1512 /* state changed by usecase */
1515 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
1520 debug_log ("intermediate state, do nothing.\n");
1521 MMPLAYER_PRINT_STATE(player);
1527 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
1528 player->sent_bos = TRUE;
1535 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
1537 return_val_if_fail( player, FALSE );
1539 if ( !player->msg_cb )
1544 //debug_log("Message (type : %d) will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1546 player->msg_cb(msgtype, param, player->msg_cb_param);
1551 static gpointer __mmplayer_next_play_thread(gpointer data)
1553 mm_player_t* player = (mm_player_t*) data;
1554 MMPlayerGstElement *mainbin = NULL;
1556 return_val_if_fail ( player, NULL );
1558 while ( ! player->next_play_thread_exit )
1560 debug_log("next play thread started. waiting for signal.\n");
1561 g_cond_wait( player->next_play_thread_cond, player->next_play_thread_mutex );
1563 debug_log("re building pipeline for next play.\n");
1565 if ( player->next_play_thread_exit )
1567 MMPLAYER_PLAYBACK_UNLOCK(player);
1569 debug_log("exiting next play thread\n");
1573 mainbin = player->pipeline->mainbin;
1575 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
1576 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
1577 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
1578 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
1579 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
1581 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
1587 static gpointer __mmplayer_repeat_thread(gpointer data)
1589 mm_player_t* player = (mm_player_t*) data;
1590 gboolean ret_value = FALSE;
1591 MMHandleType attrs = 0;
1594 return_val_if_fail ( player, NULL );
1596 while ( ! player->repeat_thread_exit )
1598 debug_log("repeat thread started. waiting for signal.\n");
1599 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1601 if ( player->repeat_thread_exit )
1603 debug_log("exiting repeat thread\n");
1607 if ( !player->cmd_lock )
1609 debug_log("can't get cmd lock\n");
1614 g_mutex_lock(player->cmd_lock);
1616 attrs = MMPLAYER_GET_ATTRS(player);
1618 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1620 debug_error("can not get play count\n");
1624 if ( player->section_repeat )
1626 ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1630 if ( player->playback_rate < 0.0 )
1632 player->resumed_by_rewind = TRUE;
1633 _mmplayer_set_mute((MMHandleType)player, 0);
1634 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1637 ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1638 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1639 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1642 player->sent_bos = FALSE;
1647 debug_error("failed to set position to zero for rewind\n");
1651 /* decrease play count */
1654 /* we successeded to rewind. update play count and then wait for next EOS */
1657 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1659 /* commit attribute */
1660 if ( mmf_attrs_commit ( attrs ) )
1662 debug_error("failed to commit attribute\n");
1667 g_mutex_unlock(player->cmd_lock);
1674 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
1676 MMHandleType attrs = 0;
1677 guint64 data_size = 0;
1679 unsigned long pos_msec = 0;
1682 return_if_fail( player && player->pipeline && player->pipeline->mainbin);
1684 __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec); // update last_position
1686 attrs = MMPLAYER_GET_ATTRS(player);
1689 debug_error("fail to get attributes.\n");
1693 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
1695 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
1697 if (stat(path, &sb) == 0)
1699 data_size = (guint64)sb.st_size;
1702 else if (MMPLAYER_IS_HTTP_STREAMING(player))
1704 data_size = player->http_content_size;
1707 __mm_player_streaming_buffering( player->streamer,
1710 player->last_position,
1713 __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1720 __mmplayer_handle_buffering_message ( mm_player_t* player )
1722 MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1723 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1724 MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1725 MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1727 return_if_fail ( player );
1729 prev_state = MMPLAYER_PREV_STATE(player);
1730 current_state = MMPLAYER_CURRENT_STATE(player);
1731 target_state = MMPLAYER_TARGET_STATE(player);
1732 pending_state = MMPLAYER_PENDING_STATE(player);
1734 if (MMPLAYER_IS_LIVE_STREAMING(player))
1737 if ( !player->streamer->is_buffering )
1739 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1740 MMPLAYER_STATE_GET_NAME(prev_state),
1741 MMPLAYER_STATE_GET_NAME(current_state),
1742 MMPLAYER_STATE_GET_NAME(pending_state),
1743 MMPLAYER_STATE_GET_NAME(target_state));
1745 /* NOTE : if buffering has done, player has to go to target state. */
1746 switch ( target_state )
1748 case MM_PLAYER_STATE_PAUSED :
1750 switch ( pending_state )
1752 case MM_PLAYER_STATE_PLAYING:
1754 __gst_pause ( player, TRUE );
1758 case MM_PLAYER_STATE_PAUSED:
1760 debug_log("player is already going to paused state, there is nothing to do.\n");
1764 case MM_PLAYER_STATE_NONE:
1765 case MM_PLAYER_STATE_NULL:
1766 case MM_PLAYER_STATE_READY:
1769 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1776 case MM_PLAYER_STATE_PLAYING :
1778 switch ( pending_state )
1780 case MM_PLAYER_STATE_NONE:
1782 if (current_state != MM_PLAYER_STATE_PLAYING)
1783 __gst_resume ( player, TRUE );
1787 case MM_PLAYER_STATE_PAUSED:
1789 /* NOTE: It should be worked as asynchronously.
1790 * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1792 __gst_resume ( player, TRUE );
1796 case MM_PLAYER_STATE_PLAYING:
1798 debug_log("player is already going to playing state, there is nothing to do.\n");
1802 case MM_PLAYER_STATE_NULL:
1803 case MM_PLAYER_STATE_READY:
1806 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1813 case MM_PLAYER_STATE_NULL :
1814 case MM_PLAYER_STATE_READY :
1815 case MM_PLAYER_STATE_NONE :
1818 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1825 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1826 * it's for stopping the pipeline clock to prevent dropping the data in sink element.
1828 switch ( pending_state )
1830 case MM_PLAYER_STATE_NONE:
1832 if (current_state != MM_PLAYER_STATE_PAUSED)
1834 debug_log("set pause state during buffering\n");
1835 __gst_pause ( player, TRUE );
1837 // to cover the weak-signal environment.
1838 if (MMPLAYER_IS_RTSP_STREAMING(player))
1840 unsigned long position = 0;
1841 gint64 pos_msec = 0;
1843 debug_log("[RTSP] seek to the buffering start point\n");
1845 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
1847 debug_error("failed to get position\n");
1852 pos_msec = position * G_GINT64_CONSTANT(1000000);
1854 __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1855 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1856 pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1862 case MM_PLAYER_STATE_PLAYING:
1864 __gst_pause ( player, TRUE );
1868 case MM_PLAYER_STATE_PAUSED:
1873 case MM_PLAYER_STATE_NULL:
1874 case MM_PLAYER_STATE_READY:
1877 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1885 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
1887 MMPlayerGstElement *textbin;
1890 return_if_fail ( player &&
1892 player->pipeline->textbin);
1894 return_if_fail ( player->pipeline->textbin[MMPLAYER_T_VIDEO_SINK].gst &&
1895 player->pipeline->textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst &&
1896 player->pipeline->textbin[MMPLAYER_T_TEXT_IDENTITY].gst);
1898 textbin = player->pipeline->textbin;
1902 debug_log("Drop subtitle text after getting EOS\n");
1904 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1905 g_object_set(textbin[MMPLAYER_T_VIDEO_SINK].gst, "async", FALSE, NULL);
1906 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1907 g_object_set(textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1909 player->is_subtitle_force_drop = TRUE;
1913 if (player->is_subtitle_force_drop == TRUE)
1915 debug_log("Enable subtitle data path without drop\n");
1917 // player->display_stat = util_get_is_connected_external_display();
1919 /* if connected with external display */
1920 if ((player->display_stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) ||
1921 (player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE))
1923 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1924 g_object_set(textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1925 g_object_set(textbin[MMPLAYER_T_VIDEO_SINK].gst, "async", TRUE, NULL);
1926 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
1928 debug_log ("connected with external display");
1932 g_object_set(textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1933 g_object_set(textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1934 g_object_set(textbin[MMPLAYER_T_VIDEO_SINK].gst, "async", FALSE, NULL);
1935 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
1937 debug_log ("non-connected with external display");
1940 player->is_subtitle_force_drop = FALSE;
1946 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1948 mm_player_t* player = (mm_player_t*) data;
1949 gboolean ret = TRUE;
1950 static gboolean async_done = FALSE;
1952 return_val_if_fail ( player, FALSE );
1953 return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1955 switch ( GST_MESSAGE_TYPE( msg ) )
1957 case GST_MESSAGE_UNKNOWN:
1958 debug_log("unknown message received\n");
1961 case GST_MESSAGE_EOS:
1963 MMHandleType attrs = 0;
1966 debug_log("GST_MESSAGE_EOS received\n");
1968 /* NOTE : EOS event is comming multiple time. watch out it */
1969 /* check state. we only process EOS when pipeline state goes to PLAYING */
1970 if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1972 debug_log("EOS received on non-playing state. ignoring it\n");
1976 __mmplayer_drop_subtitle(player, TRUE);
1978 if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) )
1982 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1984 debug_log("release audio callback\n");
1986 /* release audio callback */
1987 gst_pad_remove_buffer_probe (pad, player->audio_cb_probe_id);
1988 player->audio_cb_probe_id = 0;
1989 /* audio callback should be free because it can be called even though probe remove.*/
1990 player->audio_stream_cb = NULL;
1991 player->audio_stream_cb_user_param = NULL;
1995 /* rewind if repeat count is greater then zero */
1996 /* get play count */
1997 attrs = MMPLAYER_GET_ATTRS(player);
2001 gboolean smooth_repeat = FALSE;
2003 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
2004 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
2006 player->play_count = count;
2008 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
2010 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
2012 if ( smooth_repeat )
2014 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
2016 g_cond_signal( player->repeat_thread_cond );
2024 if ( player->section_repeat )
2026 ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
2030 if ( player->playback_rate < 0.0 )
2032 player->resumed_by_rewind = TRUE;
2033 _mmplayer_set_mute((MMHandleType)player, 0);
2034 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
2037 __mmplayer_handle_eos_delay( player, player->ini.delay_before_repeat );
2040 player->sent_bos = FALSE;
2043 if ( MM_ERROR_NONE != ret_value )
2045 debug_error("failed to set position to zero for rewind\n");
2048 /* not posting eos when repeating */
2054 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
2056 /* post eos message to application */
2057 __mmplayer_handle_eos_delay( player, player->ini.eos_delay );
2059 /* reset last position */
2060 player->last_position = 0;
2064 case GST_MESSAGE_ERROR:
2066 GError *error = NULL;
2067 gchar* debug = NULL;
2069 /* generating debug info before returning error */
2070 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
2072 /* get error code */
2073 gst_message_parse_error( msg, &error, &debug );
2075 if ( gst_structure_has_name ( msg->structure, "streaming_error" ) )
2077 /* Note : the streaming error from the streaming source is handled
2078 * using __mmplayer_handle_streaming_error.
2080 __mmplayer_handle_streaming_error ( player, msg );
2082 /* dump state of all element */
2083 __mmplayer_dump_pipeline_state( player );
2087 /* traslate gst error code to msl error code. then post it
2088 * to application if needed
2090 __mmplayer_handle_gst_error( player, msg, error );
2094 debug_error ("error debug : %s", debug);
2099 if (MMPLAYER_IS_HTTP_PD(player))
2101 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
2104 MMPLAYER_FREEIF( debug );
2105 g_error_free( error );
2109 case GST_MESSAGE_WARNING:
2112 GError* error = NULL;
2114 gst_message_parse_warning(msg, &error, &debug);
2116 debug_log("warning : %s\n", error->message);
2117 debug_log("debug : %s\n", debug);
2119 MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
2121 MMPLAYER_FREEIF( debug );
2122 g_error_free( error );
2126 case GST_MESSAGE_TAG:
2128 debug_log("GST_MESSAGE_TAG\n");
2129 if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
2131 debug_warning("failed to extract tags from gstmessage\n");
2136 case GST_MESSAGE_BUFFERING:
2138 MMMessageParamType msg_param = {0, };
2139 int asm_result = MM_ERROR_NONE;
2141 if (!MMPLAYER_IS_STREAMING(player))
2144 /* ignore the prev buffering message */
2145 if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (player->streamer->is_buffering_done == TRUE))
2147 gint buffer_percent = 0;
2149 gst_message_parse_buffering (msg, &buffer_percent);
2151 if (buffer_percent == MAX_BUFFER_PERCENT)
2153 debug_log ("Ignored all the previous buffering msg! (got %d%%)\n", buffer_percent);
2154 player->streamer->is_buffering_done = FALSE;
2160 /* update ASM state to ASM_STATE_PLAYING */
2161 /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/
2162 if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
2164 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE);
2165 if ( asm_result != MM_ERROR_NONE )
2167 debug_warning("failed to set asm state to waiting, but keep going...\n");
2171 __mmplayer_update_buffer_setting(player, msg);
2173 __mmplayer_handle_buffering_message ( player );
2175 msg_param.connection.buffering = player->streamer->buffering_percent;
2176 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
2177 if (MMPLAYER_IS_RTSP_STREAMING(player) && (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT))
2179 if (player->doing_seek)
2181 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2183 player->doing_seek = FALSE;
2184 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2186 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2195 case GST_MESSAGE_STATE_CHANGED:
2197 MMPlayerGstElement *mainbin;
2198 const GValue *voldstate, *vnewstate, *vpending;
2199 GstState oldstate, newstate, pending;
2201 if ( ! ( player->pipeline && player->pipeline->mainbin ) )
2203 debug_error("player pipeline handle is null");
2207 mainbin = player->pipeline->mainbin;
2209 /* we only handle messages from pipeline */
2210 if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
2213 /* get state info from msg */
2214 voldstate = gst_structure_get_value (msg->structure, "old-state");
2215 vnewstate = gst_structure_get_value (msg->structure, "new-state");
2216 vpending = gst_structure_get_value (msg->structure, "pending-state");
2218 oldstate = (GstState)voldstate->data[0].v_int;
2219 newstate = (GstState)vnewstate->data[0].v_int;
2220 pending = (GstState)vpending->data[0].v_int;
2222 debug_log("state changed [%s] : %s ---> %s final : %s\n",
2223 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
2224 gst_element_state_get_name( (GstState)oldstate ),
2225 gst_element_state_get_name( (GstState)newstate ),
2226 gst_element_state_get_name( (GstState)pending ) );
2228 if (oldstate == newstate)
2230 debug_log("pipeline reports state transition to old state");
2236 case GST_STATE_VOID_PENDING:
2239 case GST_STATE_NULL:
2242 case GST_STATE_READY:
2245 case GST_STATE_PAUSED:
2247 gboolean prepare_async = FALSE;
2248 gboolean is_drm = FALSE;
2250 if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction)
2251 __mmplayer_configure_audio_callback(player);
2253 if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
2255 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
2256 debug_log("checking prepare mode for async transition - %d", prepare_async);
2259 if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
2261 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
2263 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
2265 __mm_player_streaming_set_content_bitrate(player->streamer,
2266 player->total_maximum_bitrate, player->total_bitrate);
2270 /* NOTE : should consider streaming case */
2271 /* check if drm file */
2272 if ((player->pipeline->mainbin[MMPLAYER_M_SRC].gst) &&
2273 (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm")))
2275 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
2279 player->is_drm_file = TRUE;
2285 case GST_STATE_PLAYING:
2287 if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
2289 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
2290 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
2291 (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
2293 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
2297 if (player->src_changed)
2299 _mmplayer_update_content_attrs(player, ATTR_ALL);
2300 player->src_changed = FALSE;
2303 if (player->doing_seek && async_done)
2305 player->doing_seek = FALSE;
2307 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2318 case GST_MESSAGE_CLOCK_LOST:
2320 GstClock *clock = NULL;
2321 gst_message_parse_clock_lost (msg, &clock);
2322 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2323 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2325 if (((player->ini.provide_clock_for_music) && (!player->videodec_linked)) ||
2326 ((player->ini.provide_clock_for_movie) && (player->videodec_linked)))
2328 debug_log ("Provide clock is TRUE, do pause->resume\n");
2329 __gst_pause(player, FALSE);
2330 __gst_resume(player, FALSE);
2335 case GST_MESSAGE_NEW_CLOCK:
2337 GstClock *clock = NULL;
2338 gst_message_parse_new_clock (msg, &clock);
2339 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
2343 case GST_MESSAGE_ELEMENT:
2345 const gchar *structure_name;
2347 MMHandleType attrs = 0;
2349 attrs = MMPLAYER_GET_ATTRS(player);
2352 debug_error("cannot get content attribute");
2357 if(msg->structure == NULL)
2360 structure_name = gst_structure_get_name(msg->structure);
2361 if(!strcmp(structure_name, "Language_list"))
2363 const GValue *lang_list = NULL;
2364 lang_list = gst_structure_get_value (msg->structure, "lang_list");
2365 if(lang_list != NULL)
2367 count = g_list_length((GList *)g_value_get_pointer (lang_list));
2369 debug_log("Total audio tracks (from parser) = %d \n",count);
2373 if (!strcmp (structure_name, "Ext_Sub_Language_List"))
2375 const GValue *lang_list = NULL;
2376 MMPlayerLangStruct *temp = NULL;
2378 lang_list = gst_structure_get_value (msg->structure, "lang_list");
2379 if (lang_list != NULL)
2381 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2384 player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2385 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2386 if (mmf_attrs_commit (attrs))
2387 debug_error("failed to commit.\n");
2388 debug_log("Total external subtitle tracks = %d \n", count);
2392 temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2393 debug_log ("value of lang_key is %s and lang_code is %s",
2394 temp->language_key, temp->language_code);
2399 if (!strcmp (structure_name, "Int_Sub_Language_List"))
2401 const GValue *lang_list = NULL;
2402 MMPlayerLangStruct *temp = NULL;
2403 lang_list = gst_structure_get_value (msg->structure, "lang_list");
2404 if (lang_list != NULL && !player->is_external_subtitle_present)
2406 count = g_list_length ((GList *)g_value_get_pointer (lang_list));
2409 player->subtitle_language_list = (GList *)g_value_get_pointer (lang_list);
2410 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_INTERNAL].gst), "lang-list", player->subtitle_language_list, NULL);
2411 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
2412 if (mmf_attrs_commit (attrs))
2413 debug_error("failed to commit.\n");
2414 debug_log("Total internal subtitle tracks = %d \n", count);
2418 temp = g_list_nth_data (player->subtitle_language_list, count - 1);
2419 debug_log ("value of lang_key is %s and lang_code is %s",
2420 temp->language_key, temp->language_code);
2423 } else if (lang_list != NULL) {
2424 GList* internal_lang_list;
2425 internal_lang_list = (GList *)g_value_get_pointer (lang_list);
2426 debug_log ("it is internal & external case simultaneously");
2427 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_INTERNAL].gst), "lang-list", internal_lang_list, NULL);
2429 debug_error ("language list is coming null");
2433 /* custom message */
2434 if (!strcmp (structure_name, "audio_codec_not_supported")) {
2435 MMMessageParamType msg_param = {0,};
2436 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
2437 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
2442 case GST_MESSAGE_DURATION:
2444 debug_log("GST_MESSAGE_DURATION\n");
2445 ret = __mmplayer_gst_handle_duration(player, msg);
2448 debug_warning("failed to update duration");
2454 case GST_MESSAGE_ASYNC_START:
2456 debug_log("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2460 case GST_MESSAGE_ASYNC_DONE:
2462 debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2464 /* we only handle messages from pipeline */
2465 if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst )
2468 if( !MMPLAYER_IS_RTSP_STREAMING(player) )
2470 if (player->doing_seek)
2472 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
2474 player->doing_seek = FALSE;
2475 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
2477 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
2479 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
2480 (player->streamer) &&
2481 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
2482 (player->streamer->is_buffering == FALSE))
2484 GstQuery *query = NULL;
2485 gboolean busy = FALSE;
2488 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer)
2490 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
2491 if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) )
2493 gst_query_parse_buffering_percent ( query, &busy, &percent);
2495 gst_query_unref (query);
2497 debug_log("buffered percent(%s): %d\n",
2498 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
2503 player->streamer->is_buffering = FALSE;
2504 __mmplayer_handle_buffering_message(player);
2515 #if 0 /* delete unnecessary logs */
2516 case GST_MESSAGE_REQUEST_STATE: debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
2517 case GST_MESSAGE_STEP_START: debug_log("GST_MESSAGE_STEP_START\n"); break;
2518 case GST_MESSAGE_QOS: debug_log("GST_MESSAGE_QOS\n"); break;
2519 case GST_MESSAGE_PROGRESS: debug_log("GST_MESSAGE_PROGRESS\n"); break;
2520 case GST_MESSAGE_ANY: debug_log("GST_MESSAGE_ANY\n"); break;
2521 case GST_MESSAGE_INFO: debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2522 case GST_MESSAGE_STATE_DIRTY: debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
2523 case GST_MESSAGE_STEP_DONE: debug_log("GST_MESSAGE_STEP_DONE\n"); break;
2524 case GST_MESSAGE_CLOCK_PROVIDE: debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
2525 case GST_MESSAGE_STRUCTURE_CHANGE: debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
2526 case GST_MESSAGE_STREAM_STATUS: debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
2527 case GST_MESSAGE_APPLICATION: debug_log("GST_MESSAGE_APPLICATION\n"); break;
2528 case GST_MESSAGE_SEGMENT_START: debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
2529 case GST_MESSAGE_SEGMENT_DONE: debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
2530 case GST_MESSAGE_LATENCY: debug_log("GST_MESSAGE_LATENCY\n"); break;
2537 /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
2538 * gst_element_post_message api takes ownership of the message.
2540 //gst_message_unref( msg );
2546 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
2553 return_val_if_fail(player, FALSE);
2554 return_val_if_fail(msg, FALSE);
2556 gst_message_parse_duration (msg, &format, &bytes);
2558 if (MMPLAYER_IS_HTTP_STREAMING(player) && format == GST_FORMAT_BYTES )
2560 debug_log("data total size of http content: %lld", bytes);
2561 player->http_content_size = bytes;
2563 else if (format == GST_FORMAT_TIME)
2565 /* handling audio clip which has vbr. means duration is keep changing */
2566 _mmplayer_update_content_attrs (player, ATTR_DURATION );
2570 debug_warning("duration is neither BYTES or TIME");
2581 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
2584 /* macro for better code readability */
2585 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
2586 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
2588 if (string != NULL)\
2590 secure_debug_log ( "update tag string : %s\n", string); \
2591 mm_attrs_set_string_by_name(attribute, playertag, string); \
2597 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
2598 value = gst_tag_list_get_value_index(tag_list, gsttag, index); \
2601 buffer = gst_value_get_buffer (value); \
2602 secure_debug_log ( "update album cover data : %p, size : %d\n", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
2603 MMPLAYER_FREEIF(player->album_art); \
2604 player->album_art = (gchar *)g_malloc(GST_BUFFER_SIZE(buffer)); \
2605 if (player->album_art) \
2607 memcpy(player->album_art, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
2608 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, GST_BUFFER_SIZE(buffer)); \
2609 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) \
2611 msg_param.data = (void *)player->album_art; \
2612 msg_param.size = GST_BUFFER_SIZE(buffer); \
2613 MMPLAYER_POST_MSG (player, MM_MESSAGE_IMAGE_BUFFER, &msg_param); \
2614 secure_debug_log ( "post message image buffer data : %p, size : %d\n", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
2619 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
2620 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
2624 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) \
2626 if (player->updated_bitrate_count == 0) \
2627 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
2628 if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2630 player->bitrate[player->updated_bitrate_count] = v_uint;\
2631 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
2632 player->updated_bitrate_count++; \
2633 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
2634 secure_debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
2637 else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) \
2639 if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
2641 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
2642 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
2643 player->updated_maximum_bitrate_count++; \
2644 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
2645 secure_debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
2650 mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
2656 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
2657 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
2661 string = g_strdup_printf("%d", g_date_get_year(date));\
2662 mm_attrs_set_string_by_name(attribute, playertag, string);\
2663 secure_debug_log ( "metainfo year : %s\n", string);\
2664 MMPLAYER_FREEIF(string);\
2669 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
2670 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
2674 /* FIXIT : don't know how to store date */\
2680 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
2681 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
2685 /* FIXIT : don't know how to store date */\
2691 /* function start */
2692 GstTagList* tag_list = NULL;
2694 MMHandleType attrs = 0;
2696 char *string = NULL;
2700 GstBuffer *buffer = NULL;
2702 const GValue *value;
2703 MMMessageParamType msg_param = {0, };
2705 /* currently not used. but those are needed for above macro */
2706 //guint64 v_uint64 = 0;
2707 //gdouble v_double = 0;
2709 return_val_if_fail( player && msg, FALSE );
2711 attrs = MMPLAYER_GET_ATTRS(player);
2713 return_val_if_fail( attrs, FALSE );
2715 /* get tag list from gst message */
2716 gst_message_parse_tag(msg, &tag_list);
2718 /* store tags to player attributes */
2719 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
2720 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
2721 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
2722 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
2723 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
2724 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
2725 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
2726 MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
2727 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
2728 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
2729 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
2730 MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
2731 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
2732 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
2733 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
2734 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
2735 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
2736 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
2737 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
2738 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
2739 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
2740 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
2741 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
2742 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
2743 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
2744 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
2745 /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
2746 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
2747 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
2748 MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
2749 MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
2750 MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
2751 MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
2752 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
2753 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
2754 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
2755 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
2756 /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
2757 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
2758 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
2759 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
2760 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
2761 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
2762 /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
2763 /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
2765 if ( mmf_attrs_commit ( attrs ) )
2766 debug_error("failed to commit.\n");
2768 gst_tag_list_free(tag_list);
2774 __mmplayer_gst_rtp_no_more_pads (GstElement *element, gpointer data) // @
2776 mm_player_t* player = (mm_player_t*) data;
2780 /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2781 * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2782 * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
2783 * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2785 * [1] audio and video will be dumped with filesink.
2786 * [2] autoplugging is done by just using pad caps.
2787 * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2788 * and the video will be dumped via filesink.
2790 if ( player->num_dynamic_pad == 0 )
2792 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2794 if ( ! __mmplayer_gst_remove_fakesink( player,
2795 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
2797 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2798 * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
2799 * source element are not same. To overcome this situation, this function will called
2800 * several places and several times. Therefore, this is not an error case.
2806 /* create dot before error-return. for debugging */
2807 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
2809 player->no_more_pad = TRUE;
2815 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
2817 GstElement* parent = NULL;
2819 return_val_if_fail(player && player->pipeline, FALSE);
2821 /* if we have no fakesink. this meas we are using decodebin2 which doesn'
2822 t need to add extra fakesink */
2823 return_val_if_fail(fakesink, TRUE);
2826 g_mutex_lock( player->fsink_lock );
2828 if ( ! fakesink->gst )
2833 /* get parent of fakesink */
2834 parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
2837 debug_log("fakesink already removed\n");
2841 gst_element_set_locked_state( fakesink->gst, TRUE );
2843 /* setting the state to NULL never returns async
2844 * so no need to wait for completion of state transiton
2846 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
2848 debug_error("fakesink state change failure!\n");
2850 /* FIXIT : should I return here? or try to proceed to next? */
2854 /* remove fakesink from it's parent */
2855 if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
2857 debug_error("failed to remove fakesink\n");
2859 gst_object_unref( parent );
2864 gst_object_unref( parent );
2866 debug_log("state-holder removed\n");
2868 gst_element_set_locked_state( fakesink->gst, FALSE );
2870 g_mutex_unlock( player->fsink_lock );
2874 if ( fakesink->gst )
2876 gst_element_set_locked_state( fakesink->gst, FALSE );
2879 g_mutex_unlock( player->fsink_lock );
2885 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2887 GstPad *sinkpad = NULL;
2888 GstCaps* caps = NULL;
2889 GstElement* new_element = NULL;
2890 GstStructure* str = NULL;
2891 const gchar* name = NULL;
2893 mm_player_t* player = (mm_player_t*) data;
2897 return_if_fail( element && pad );
2898 return_if_fail( player &&
2900 player->pipeline->mainbin );
2903 /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2904 * num_dynamic_pad will decreased after creating a sinkbin.
2906 player->num_dynamic_pad++;
2907 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2909 /* perform autoplugging if dump is disabled */
2910 if ( player->ini.rtsp_do_typefinding )
2912 /* create typefind */
2913 new_element = gst_element_factory_make( "typefind", NULL );
2914 if ( ! new_element )
2916 debug_error("failed to create typefind\n");
2920 MMPLAYER_SIGNAL_CONNECT( player,
2921 G_OBJECT(new_element),
2922 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
2924 G_CALLBACK(__mmplayer_typefind_have_type),
2927 /* FIXIT : try to remove it */
2928 player->have_dynamic_pad = FALSE;
2930 else /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2932 debug_log("using pad caps to autopluging instead of doing typefind\n");
2934 caps = gst_pad_get_caps( pad );
2936 MMPLAYER_CHECK_NULL( caps );
2938 /* clear previous result*/
2939 player->have_dynamic_pad = FALSE;
2941 str = gst_caps_get_structure(caps, 0);
2945 debug_error ("cannot get structure from capse.\n");
2949 name = gst_structure_get_name (str);
2952 debug_error ("cannot get mimetype from structure.\n");
2956 if (strstr(name, "video"))
2959 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
2961 if (stype == MM_DISPLAY_SURFACE_NULL)
2963 if (player->v_stream_caps)
2965 gst_caps_unref(player->v_stream_caps);
2966 player->v_stream_caps = NULL;
2969 new_element = gst_element_factory_make("fakesink", NULL);
2970 player->num_dynamic_pad--;
2975 /* clear previous result*/
2976 player->have_dynamic_pad = FALSE;
2978 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
2980 debug_error("failed to autoplug for caps");
2984 /* check if there's dynamic pad*/
2985 if( player->have_dynamic_pad )
2987 debug_error("using pad caps assums there's no dynamic pad !\n");
2988 debug_error("try with enalbing rtsp_do_typefinding\n");
2992 gst_caps_unref( caps );
2998 /* excute new_element if created*/
3001 debug_log("adding new element to pipeline\n");
3003 /* set state to READY before add to bin */
3004 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
3006 /* add new element to the pipeline */
3007 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element) )
3009 debug_error("failed to add autoplug element to bin\n");
3013 /* get pad from element */
3014 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
3017 debug_error("failed to get sinkpad from autoplug element\n");
3022 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3024 debug_error("failed to link autoplug element\n");
3028 gst_object_unref (sinkpad);
3031 /* run. setting PLAYING here since streamming source is live source */
3032 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3039 STATE_CHANGE_FAILED:
3041 /* FIXIT : take care if new_element has already added to pipeline */
3043 gst_object_unref(GST_OBJECT(new_element));
3046 gst_object_unref(GST_OBJECT(sinkpad));
3049 gst_object_unref(GST_OBJECT(caps));
3051 /* FIXIT : how to inform this error to MSL ????? */
3052 /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3053 * then post an error to application
3059 /* FIXIT : check indent */
3061 __mmplayer_gst_wfd_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
3063 GstPad *sinkpad = NULL;
3064 GstCaps* caps = NULL;
3065 GstElement* new_element = NULL;
3066 enum MainElementID element_id = MMPLAYER_M_NUM;
3068 mm_player_t* player = (mm_player_t*) data;
3072 return_if_fail( element && pad );
3073 return_if_fail( player &&
3075 player->pipeline->mainbin );
3077 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
3080 debug_log("using pad caps to autopluging instead of doing typefind\n");
3081 caps = gst_pad_get_caps( pad );
3082 MMPLAYER_CHECK_NULL( caps );
3083 /* clear previous result*/
3084 player->have_dynamic_pad = FALSE;
3085 new_element = gst_element_factory_make("rtpmp2tdepay", "wfd_rtp_depay");
3088 debug_error ( "failed to create wfd rtp depay element\n" );
3091 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
3092 /* add new element to the pipeline */
3093 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element) )
3095 debug_log("failed to add autoplug element to bin\n");
3098 /* get pad from element */
3099 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
3102 debug_log("failed to get sinkpad from autoplug element\n");
3106 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3108 debug_log("failed to link autoplug element\n");
3111 gst_object_unref (sinkpad);
3113 pad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "src" );
3114 caps = gst_pad_get_caps( pad );
3115 MMPLAYER_CHECK_NULL( caps );
3116 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3117 /* create typefind */
3118 new_element = gst_element_factory_make( "typefind", NULL );
3119 if ( ! new_element )
3121 debug_log("failed to create typefind\n");
3125 MMPLAYER_SIGNAL_CONNECT( player,
3126 G_OBJECT(new_element),
3127 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
3129 G_CALLBACK(__mmplayer_typefind_have_type),
3132 player->have_dynamic_pad = FALSE;
3135 /* excute new_element if created*/
3138 debug_log("adding new element to pipeline\n");
3140 /* set state to READY before add to bin */
3141 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
3143 /* add new element to the pipeline */
3144 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element) )
3146 debug_log("failed to add autoplug element to bin\n");
3150 /* get pad from element */
3151 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
3154 debug_log("failed to get sinkpad from autoplug element\n");
3159 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
3161 debug_log("failed to link autoplug element\n");
3165 gst_object_unref (sinkpad);
3168 /* run. setting PLAYING here since streamming source is live source */
3169 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
3172 /* store handle to futher manipulation */
3173 player->pipeline->mainbin[element_id].id = element_id;
3174 player->pipeline->mainbin[element_id].gst = new_element;
3180 STATE_CHANGE_FAILED:
3182 /* FIXIT : take care if new_element has already added to pipeline */
3184 gst_object_unref(GST_OBJECT(new_element));
3187 gst_object_unref(GST_OBJECT(sinkpad));
3190 gst_object_unref(GST_OBJECT(caps));
3192 /* FIXIT : how to inform this error to MSL ????? */
3193 /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
3194 * then post an error to application
3199 __mmplayer_gst_selector_blocked (GstPad* pad, gboolean blocked, gpointer data)
3201 debug_log ("pad blocked callback, blocked: %d", blocked);
3205 __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data)
3207 mm_player_t* player = NULL;
3208 GstElement* pipeline = NULL;
3209 GstElement* selector = NULL;
3210 GstElement* fakesink = NULL;
3211 GstCaps* caps = NULL;
3212 GstStructure* str = NULL;
3213 const gchar* name = NULL;
3214 GstPad* sinkpad = NULL;
3215 GstPad* srcpad = NULL;
3216 gboolean first_track = FALSE;
3218 enum MainElementID elemId = MMPLAYER_M_NUM;
3221 player = (mm_player_t*)data;
3223 return_if_fail (elem && pad);
3224 return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3226 //debug_log ("pad-added signal handling\n");
3228 pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3230 /* get mimetype from caps */
3231 caps = gst_pad_get_caps (pad);
3234 debug_error ("cannot get caps from pad.\n");
3238 str = gst_caps_get_structure (caps, 0);
3241 debug_error ("cannot get structure from capse.\n");
3245 name = gst_structure_get_name (str);
3248 debug_error ("cannot get mimetype from structure.\n");
3252 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3253 //debug_log ("detected mimetype : %s\n", name);
3255 if (strstr(name, "video"))
3258 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
3260 /* don't make video because of not required, and not support multiple track */
3261 if (stype == MM_DISPLAY_SURFACE_NULL)
3263 debug_log ("no video sink by null surface or multiple track");
3264 gchar *caps_str = gst_caps_to_string(caps);
3265 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
3267 player->set_mode.video_zc = TRUE;
3269 MMPLAYER_FREEIF( caps_str );
3271 if (player->v_stream_caps)
3273 gst_caps_unref(player->v_stream_caps);
3274 player->v_stream_caps = NULL;
3277 debug_log ("create fakesink instead of videobin");
3280 fakesink = gst_element_factory_make ("fakesink", NULL);
3281 if (fakesink == NULL)
3283 debug_error ("ERROR : fakesink create error\n");
3287 player->video_fakesink = fakesink;
3289 gst_bin_add (GST_BIN(pipeline), fakesink);
3292 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3294 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3296 debug_warning ("failed to link fakesink\n");
3297 gst_object_unref (GST_OBJECT(fakesink));
3301 if (player->set_mode.media_packet_video_stream)
3302 player->video_cb_probe_id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (__mmplayer_video_stream_probe), player);
3304 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3305 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3306 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3311 debug_log ("video selector \n");
3312 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
3316 if (strstr(name, "audio"))
3318 gint samplerate = 0;
3321 debug_log ("audio selector \n");
3322 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
3324 gst_structure_get_int (str, "rate", &samplerate);
3325 gst_structure_get_int (str, "channels", &channels);
3327 if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
3329 fakesink = gst_element_factory_make ("fakesink", NULL);
3330 if (fakesink == NULL)
3332 debug_error ("ERROR : fakesink create error\n");
3336 gst_bin_add (GST_BIN(pipeline), fakesink);
3339 sinkpad = gst_element_get_static_pad (fakesink, "sink");
3341 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3343 debug_warning ("failed to link fakesink\n");
3344 gst_object_unref (GST_OBJECT(fakesink));
3348 g_object_set (G_OBJECT (fakesink), "async", TRUE, NULL);
3349 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
3350 gst_element_set_state (fakesink, GST_STATE_PAUSED);
3355 else if (strstr(name, "text"))
3357 debug_log ("text selector \n");
3358 elemId = MMPLAYER_M_T_SUBMUX_INTERNAL;
3362 debug_error ("wrong elem id \n");
3367 selector = player->pipeline->mainbin[elemId].gst;
3369 if (selector == NULL)
3371 if (strstr(name, "audio") || strstr(name, "video")) {
3372 selector = gst_element_factory_make ("input-selector", NULL);
3373 debug_log ("Creating input-selector\n");
3374 if (selector == NULL)
3376 debug_error ("ERROR : input-selector create error\n");
3379 g_object_set (selector, "sync-streams", TRUE, NULL);
3383 if (player->textsink_linked)
3385 selector = gst_element_factory_make ("input-selector", "text-inselector");
3386 debug_log ("Creating input-selector\n");
3390 selector = gst_element_factory_make ("submux", "internal-submux");
3391 g_object_set (G_OBJECT (selector), "lang-list", player->subtitle_language_list, NULL);
3392 debug_log ("Creating submux\n");
3394 if (selector == NULL)
3396 debug_error ("ERROR : input-selector create error\n");
3399 debug_log ("Created submux %p\n", selector);
3401 gst_bin_add (GST_BIN(pipeline), selector);
3402 gst_element_set_state (selector, GST_STATE_PAUSED);
3404 player->pipeline->mainbin[elemId].id = elemId;
3405 player->pipeline->mainbin[elemId].gst = selector;
3408 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK; // default
3410 srcpad = gst_element_get_static_pad (selector, "src");
3412 debug_log ("blocking %" GST_PTR_FORMAT, srcpad);
3413 gst_pad_set_blocked_async (srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3417 debug_log ("input-selector is already created.\n");
3418 selector = player->pipeline->mainbin[elemId].gst;
3422 debug_log ("Calling request pad with selector %p \n", selector);
3423 sinkpad = gst_element_get_request_pad (selector, "sink%d");
3425 debug_log ("got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad));
3427 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad))
3429 debug_warning ("failed to link selector\n");
3430 gst_object_unref (GST_OBJECT(selector));
3434 if (first_track && (strstr(name, "audio") || strstr(name, "video")))
3436 debug_log ("this is first track --> active track \n");
3437 g_object_set (selector, "active-pad", sinkpad, NULL);
3439 debug_log ("subtitle is of internal type \n");
3440 if(!player->textsink_linked) {
3441 g_object_set (selector, "is-internal", TRUE, NULL);
3443 debug_log ("this is first track --> active track \n");
3444 g_object_set (selector, "active-pad", sinkpad, NULL);
3453 gst_caps_unref (caps);
3458 gst_object_unref (GST_OBJECT(sinkpad));
3464 gst_object_unref (GST_OBJECT(srcpad));
3471 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
3473 #define DEFAULT_TRACK 0
3474 GstPad* srcpad = NULL;
3475 MMHandleType attrs = 0;
3476 gint active_index = 0;
3478 // [link] input-selector :: textbin
3479 srcpad = gst_element_get_static_pad (text_selector, "src");
3482 debug_error("failed to get srcpad from selector\n");
3486 debug_log ("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
3488 active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
3489 if ((active_index != DEFAULT_TRACK) &&
3490 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE))
3492 debug_warning("failed to change text track\n");
3493 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
3496 player->no_more_pad = TRUE;
3497 __mmplayer_gst_decode_callback (text_selector, srcpad, player);
3499 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
3500 gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3502 debug_log("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3504 if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
3505 player->has_closed_caption = TRUE;
3507 attrs = MMPLAYER_GET_ATTRS(player);
3510 mm_attrs_set_int_by_name(attrs, "content_text_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
3511 if (mmf_attrs_commit (attrs))
3512 debug_error("failed to commit.\n");
3516 debug_error("cannot get content attribute");
3521 gst_object_unref ( GST_OBJECT(srcpad) );
3526 int _mmplayer_gst_set_audio_channel(MMHandleType hplayer, MMPlayerAudioChannel ch_idx)
3528 int result = MM_ERROR_NONE;
3530 mm_player_t* player = (mm_player_t*)hplayer;
3531 MMPlayerGstElement* mainbin = NULL;
3532 gchar* change_pad_name = NULL;
3533 GstPad* sinkpad = NULL;
3534 GstCaps* caps = NULL;
3538 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3540 debug_log ("Change Audio mode to %d\n", ch_idx);
3541 player->use_deinterleave = TRUE;
3543 if ((!player->pipeline) || (!player->pipeline->mainbin))
3545 debug_log ("pre setting : %d\n", ch_idx);
3547 player->audio_mode.active_pad_index = ch_idx;
3551 mainbin = player->pipeline->mainbin;
3553 if (mainbin[MMPLAYER_M_A_SELECTOR].gst == NULL)
3555 if (player->max_audio_channels < 2)
3557 debug_log ("mono channel track only\n");
3561 debug_warning ("selector doesn't exist\n");
3562 return result; /* keep playing */
3565 debug_log ("total_ch_num : %d\n", player->audio_mode.total_track_num);
3567 if (player->audio_mode.total_track_num < 2)
3569 debug_warning ("there is no another audio path\n");
3570 return result; /* keep playing */
3573 if ((ch_idx < 0) || (ch_idx >= player->audio_mode.total_track_num))
3575 debug_warning ("Not a proper ch_idx : %d \n", ch_idx);
3576 return result; /* keep playing */
3579 /*To get the new pad from the selector*/
3580 change_pad_name = g_strdup_printf ("sink%d", ch_idx);
3581 if (change_pad_name == NULL)
3583 debug_warning ("Pad does not exists\n");
3584 goto ERROR; /* keep playing */
3587 debug_log ("new active pad name: %s\n", change_pad_name);
3589 sinkpad = gst_element_get_static_pad (mainbin[MMPLAYER_M_A_SELECTOR].gst, change_pad_name);
3590 if (sinkpad == NULL)
3592 //result = MM_ERROR_PLAYER_INTERNAL;
3593 goto ERROR; /* keep playing */
3596 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3597 g_object_set (mainbin[MMPLAYER_M_A_SELECTOR].gst, "active-pad", sinkpad, NULL);
3599 caps = GST_PAD_CAPS(sinkpad);
3600 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3602 __mmplayer_set_audio_attrs (player, caps);
3603 player->audio_mode.active_pad_index = ch_idx;
3608 gst_object_unref (sinkpad);
3610 MMPLAYER_FREEIF(change_pad_name);
3619 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
3621 mm_player_t* player = (mm_player_t*)data;
3622 GstElement* selector = NULL;
3623 GstElement* queue = NULL;
3625 GstPad* srcpad = NULL;
3626 GstPad* sinkpad = NULL;
3627 gchar* caps_str= NULL;
3630 return_if_fail (player && player->pipeline && player->pipeline->mainbin);
3632 caps_str = gst_caps_to_string(GST_PAD_CAPS(pad));
3633 debug_log ("deinterleave new caps : %s\n", caps_str);
3634 MMPLAYER_FREEIF(caps_str);
3636 if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL)
3638 debug_error ("ERROR : queue create error\n");
3642 g_object_set(G_OBJECT(queue),
3643 "max-size-buffers", 10,
3644 "max-size-bytes", 0,
3645 "max-size-time", (guint64)0,
3648 selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3652 debug_error("there is no audio channel selector.\n");
3656 srcpad = gst_element_get_static_pad (queue, "src");
3657 sinkpad = gst_element_get_request_pad (selector, "sink%d");
3659 debug_log ("link (%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
3661 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3663 debug_warning ("failed to link deinterleave - selector\n");
3667 gst_element_set_state (queue, GST_STATE_PAUSED);
3668 player->audio_mode.total_track_num++;
3674 gst_object_unref ( GST_OBJECT(srcpad) );
3680 gst_object_unref ( GST_OBJECT(sinkpad) );
3689 __mmplayer_gst_deinterleave_no_more_pads (GstElement *elem, gpointer data)
3691 mm_player_t* player = NULL;
3692 GstElement* selector = NULL;
3693 GstPad* sinkpad = NULL;
3694 gint active_index = 0;
3695 gchar* change_pad_name = NULL;
3696 GstCaps* caps = NULL; // no need to unref
3699 player = (mm_player_t*) data;
3701 selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
3705 debug_error("there is no audio channel selector.\n");
3709 active_index = player->audio_mode.active_pad_index;
3711 if (active_index != DEFAULT_AUDIO_CH)
3713 gint audio_ch = DEFAULT_AUDIO_CH;
3715 /*To get the new pad from the selector*/
3716 change_pad_name = g_strdup_printf ("sink%d", active_index);
3717 if (change_pad_name != NULL)
3719 sinkpad = gst_element_get_static_pad (selector, change_pad_name);
3720 if (sinkpad != NULL)
3722 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
3723 g_object_set (selector, "active-pad", sinkpad, NULL);
3725 audio_ch = active_index;
3727 caps = GST_PAD_CAPS(sinkpad);
3728 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3730 __mmplayer_set_audio_attrs (player, caps);
3734 player->audio_mode.active_pad_index = audio_ch;
3735 debug_log("audio LR info (0:stereo) = %d\n", player->audio_mode.active_pad_index);
3741 gst_object_unref (sinkpad);
3748 __mmplayer_gst_build_deinterleave_path (GstElement *elem, GstPad *pad, gpointer data)
3750 mm_player_t* player = NULL;
3751 MMPlayerGstElement *mainbin = NULL;
3753 GstElement* tee = NULL;
3754 GstElement* stereo_queue = NULL;
3755 GstElement* mono_queue = NULL;
3756 GstElement* conv = NULL;
3757 GstElement* filter = NULL;
3758 GstElement* deinterleave = NULL;
3759 GstElement* selector = NULL;
3761 GstPad* srcpad = NULL;
3762 GstPad* selector_srcpad = NULL;
3763 GstPad* sinkpad = NULL;
3764 GstCaps* caps = NULL;
3769 player = (mm_player_t*) data;
3771 return_if_fail( elem && pad );
3772 return_if_fail( player && player->pipeline && player->pipeline->mainbin );
3774 mainbin = player->pipeline->mainbin;
3777 if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL)
3779 debug_error ("ERROR : tee create error\n");
3783 mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
3784 mainbin[MMPLAYER_M_A_TEE].gst = tee;
3786 gst_element_set_state (tee, GST_STATE_PAUSED);
3789 srcpad = gst_element_get_request_pad (tee, "src%d");
3790 if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3792 debug_error ("ERROR : stereo queue create error\n");
3796 g_object_set(G_OBJECT(stereo_queue),
3797 "max-size-buffers", 10,
3798 "max-size-bytes", 0,
3799 "max-size-time", (guint64)0,
3802 player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
3803 player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
3807 gst_object_unref (GST_OBJECT(srcpad));
3811 srcpad = gst_element_get_request_pad (tee, "src%d");
3813 if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL)
3815 debug_error ("ERROR : mono queue create error\n");
3819 g_object_set(G_OBJECT(mono_queue),
3820 "max-size-buffers", 10,
3821 "max-size-bytes", 0,
3822 "max-size-time", (guint64)0,
3825 player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3826 player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3828 gst_element_set_state (stereo_queue, GST_STATE_PAUSED);
3829 gst_element_set_state (mono_queue, GST_STATE_PAUSED);
3832 srcpad = gst_element_get_static_pad (mono_queue, "src");
3833 if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL)
3835 debug_error ("ERROR : audioconvert create error\n");
3839 player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3840 player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3845 gst_object_unref (GST_OBJECT(srcpad));
3848 srcpad = gst_element_get_static_pad (conv, "src");
3850 if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL)
3852 debug_error ("ERROR : capsfilter create error\n");
3856 player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3857 player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3859 caps = gst_caps_from_string( "audio/x-raw-int, "
3860 "width = (int) 16, "
3861 "depth = (int) 16, "
3862 "channels = (int) 2");
3864 g_object_set (GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL );
3865 gst_caps_unref( caps );
3867 gst_element_set_state (conv, GST_STATE_PAUSED);
3868 gst_element_set_state (filter, GST_STATE_PAUSED);
3873 gst_object_unref (GST_OBJECT(srcpad));
3876 srcpad = gst_element_get_static_pad (filter, "src");
3878 if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL)
3880 debug_error ("ERROR : deinterleave create error\n");
3884 g_object_set (deinterleave, "keep-positions", TRUE, NULL);
3886 MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3887 G_CALLBACK (__mmplayer_gst_deinterleave_pad_added), player);
3889 MMPLAYER_SIGNAL_CONNECT (player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3890 G_CALLBACK (__mmplayer_gst_deinterleave_no_more_pads), player);
3892 player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3893 player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3896 selector = gst_element_factory_make ("input-selector", "audio-channel-selector");
3897 if (selector == NULL)
3899 debug_error ("ERROR : audio-selector create error\n");
3903 g_object_set (selector, "sync-streams", TRUE, NULL);
3904 gst_bin_add (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3906 player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3907 player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3909 selector_srcpad = gst_element_get_static_pad (selector, "src");
3911 debug_log ("blocking %" GST_PTR_FORMAT, selector_srcpad);
3912 gst_pad_set_blocked_async (selector_srcpad, TRUE, __mmplayer_gst_selector_blocked, NULL);
3916 gst_object_unref (GST_OBJECT(srcpad));
3920 srcpad = gst_element_get_static_pad(stereo_queue, "src");
3921 sinkpad = gst_element_get_request_pad (selector, "sink%d");
3923 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
3925 debug_warning ("failed to link queue_stereo - selector\n");
3929 player->audio_mode.total_track_num++;
3931 g_object_set (selector, "active-pad", sinkpad, NULL);
3932 gst_element_set_state (deinterleave, GST_STATE_PAUSED);
3933 gst_element_set_state (selector, GST_STATE_PAUSED);
3935 __mmplayer_gst_decode_callback (selector, selector_srcpad, player);
3937 debug_log ("unblocking %" GST_PTR_FORMAT, selector_srcpad);
3938 gst_pad_set_blocked_async (selector_srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
3943 gst_object_unref (GST_OBJECT(sinkpad));
3949 gst_object_unref (GST_OBJECT(srcpad));
3953 if (selector_srcpad)
3955 gst_object_unref (GST_OBJECT(selector_srcpad));
3956 selector_srcpad = NULL;
3964 __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data)
3966 mm_player_t* player = NULL;
3967 GstPad* srcpad = NULL;
3968 GstElement* video_selector = NULL;
3969 GstElement* audio_selector = NULL;
3970 GstElement* text_selector = NULL;
3971 MMHandleType attrs = 0;
3972 gint active_index = 0;
3973 GstFormat fmt = GST_FORMAT_BYTES;
3974 gint64 dur_bytes = 0L;
3976 player = (mm_player_t*) data;
3978 debug_log("no-more-pad signal handling\n");
3980 if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3981 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
3983 debug_warning("no need to go more");
3985 if (player->pp_rebuilding)
3987 player->pp_rebuilding = FALSE;
3988 MMPLAYER_PLAYBACK_UNLOCK(player);
3994 if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3995 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3996 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3997 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
3999 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
4001 if (NULL == player->streamer)
4003 debug_warning("invalid state for buffering");
4007 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
4008 guint buffer_bytes = init_buffering_time * ESTIMATED_BUFFER_UNIT;
4010 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
4011 debug_log("[Decodebin2] set use-buffering on Q2 (pre buffer time: %d sec, buffer size : %d)\n", (gint)init_buffering_time, buffer_bytes);
4013 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
4015 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
4016 debug_error("fail to get duration.\n");
4018 // enable use-buffering on queue2 instead of multiqueue (ex)audio only streaming
4019 // use file information was already set on Q2 when it was created.
4020 __mm_player_streaming_set_queue2(player->streamer,
4021 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
4022 TRUE, // use_buffering
4024 init_buffering_time,
4026 player->ini.http_buffering_limit, // high percent
4029 ((dur_bytes>0)?((guint64)dur_bytes):0));
4032 video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
4033 audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
4034 text_selector = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_INTERNAL].gst;
4038 // the first track can be played only. not support track changing yet.
4039 // [link] input-selector :: videobin
4040 srcpad = gst_element_get_static_pad (video_selector, "src");
4043 debug_error("failed to get srcpad from video selector\n");
4047 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
4048 if ((!text_selector) && (!audio_selector))
4049 player->no_more_pad = TRUE;
4051 __mmplayer_gst_decode_callback (video_selector, srcpad, player);
4053 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
4054 gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
4056 debug_log("Total video tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num);
4058 gst_object_unref ( GST_OBJECT(srcpad) );
4063 if ((player->pipeline->videobin) && (player->pipeline->videobin[MMPLAYER_V_BIN].gst))
4065 debug_log ("There is no video track : remove videobin");
4067 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN );
4068 __mmplayer_del_sink ( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
4070 MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->videobin, MMPLAYER_V_BIN );
4071 MMPLAYER_FREEIF ( player->pipeline->videobin )
4077 #define DEFAULT_TRACK 0
4078 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
4079 if ((active_index != DEFAULT_TRACK) &&
4080 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE))
4082 debug_warning("failed to change audio track\n");
4083 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
4086 // [link] input-selector :: audiobin
4087 srcpad = gst_element_get_static_pad (audio_selector, "src");
4090 debug_error("failed to get srcpad from selector\n");
4094 debug_log ("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
4096 player->no_more_pad = TRUE;
4098 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2))
4100 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
4101 gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
4103 __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
4107 __mmplayer_gst_decode_callback (audio_selector, srcpad, player);
4109 debug_log ("unblocking %" GST_PTR_FORMAT, srcpad);
4110 gst_pad_set_blocked_async (srcpad, FALSE, __mmplayer_gst_selector_blocked, NULL);
4113 debug_log("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
4115 attrs = MMPLAYER_GET_ATTRS(player);
4118 mm_attrs_set_int_by_name(attrs, "content_audio_track_num",(gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
4119 if (mmf_attrs_commit (attrs))
4120 debug_error("failed to commit.\n");
4124 debug_error("cannot get content attribute");
4129 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst))
4131 debug_log ("There is no audio track : remove audiobin");
4133 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN );
4134 __mmplayer_del_sink ( player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst );
4136 MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN );
4137 MMPLAYER_FREEIF ( player->pipeline->audiobin )
4143 __mmplayer_handle_text_decode_path(player, text_selector);
4151 gst_object_unref ( GST_OBJECT(srcpad) );
4155 if (player->pp_rebuilding)
4157 player->pp_rebuilding = FALSE;
4158 MMPLAYER_PLAYBACK_UNLOCK(player);
4163 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // @
4165 mm_player_t* player = NULL;
4166 MMHandleType attrs = 0;
4167 GstElement* pipeline = NULL;
4168 GstCaps* caps = NULL;
4169 gchar* caps_str = NULL;
4170 GstStructure* str = NULL;
4171 const gchar* name = NULL;
4172 GstPad* sinkpad = NULL;
4173 GstElement* sinkbin = NULL;
4174 gboolean reusing = FALSE;
4175 GstElement *text_selector = NULL;
4178 player = (mm_player_t*) data;
4180 return_if_fail( elem && pad );
4181 return_if_fail(player && player->pipeline && player->pipeline->mainbin);
4183 pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
4185 attrs = MMPLAYER_GET_ATTRS(player);
4188 debug_error("cannot get content attribute\n");
4192 /* get mimetype from caps */
4193 caps = gst_pad_get_caps( pad );
4196 debug_error("cannot get caps from pad.\n");
4199 caps_str = gst_caps_to_string(caps);
4201 str = gst_caps_get_structure( caps, 0 );
4204 debug_error("cannot get structure from capse.\n");
4208 name = gst_structure_get_name(str);
4211 debug_error("cannot get mimetype from structure.\n");
4215 //debug_log("detected mimetype : %s\n", name);
4217 if (strstr(name, "audio"))
4219 if (player->pipeline->audiobin == NULL)
4221 if (MM_ERROR_NONE != __mmplayer_gst_create_audio_pipeline(player))
4223 debug_error("failed to create audiobin. continuing without audio\n");
4227 sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4228 debug_log("creating audiosink bin success\n");
4233 sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
4234 debug_log("reusing audiobin\n");
4235 _mmplayer_update_content_attrs( player, ATTR_AUDIO);
4238 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
4239 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
4241 player->audiosink_linked = 1;
4243 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4246 debug_error("failed to get pad from sinkbin\n");
4250 else if (strstr(name, "video"))
4252 if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12"))
4254 player->set_mode.video_zc = TRUE;
4257 if (player->pipeline->videobin == NULL)
4259 /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
4260 /* get video surface type */
4261 int surface_type = 0;
4262 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
4264 if (surface_type == MM_DISPLAY_SURFACE_NULL)
4266 debug_log("not make videobin because it dose not want\n");
4270 if (MM_ERROR_NONE != __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
4272 debug_error("failed to create videobin. continuing without video\n");
4276 sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4277 debug_log("creating videosink bin success\n");
4282 sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
4283 debug_log("re-using videobin\n");
4284 _mmplayer_update_content_attrs( player, ATTR_VIDEO);
4287 /* FIXIT : track number shouldn't be hardcoded */
4288 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
4289 player->videosink_linked = 1;
4291 /* NOTE : intermediate code before doing H/W subtitle compositon */
4292 if ( player->use_textoverlay && player->play_subtitle )
4294 debug_log("using textoverlay for external subtitle");
4295 /* check text bin has created well */
4296 if ( player->pipeline && player->pipeline->textbin )
4298 /* get sinkpad from textoverlay */
4299 sinkpad = gst_element_get_static_pad(
4300 GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4304 debug_error("failed to get sink pad from textoverlay");
4308 /* link new pad with textoverlay first */
4309 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
4311 debug_error("failed to get pad from sinkbin\n");
4315 gst_object_unref(sinkpad);
4318 /* alright, override pad to textbin.src for futher link */
4319 pad = gst_element_get_static_pad(
4320 GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst),
4324 debug_error("failed to get sink pad from textoverlay");
4330 debug_error("should not reach here.");
4335 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
4338 debug_error("failed to get pad from sinkbin\n");
4342 else if (strstr(name, "text"))
4344 if (player->pipeline->textbin == NULL)
4346 MMPlayerGstElement* mainbin = NULL;
4348 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
4350 debug_error("failed to create textbin. continuing without text\n");
4354 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4355 debug_log("creating textink bin success\n");
4357 /* FIXIT : track number shouldn't be hardcoded */
4358 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
4360 player->textsink_linked = 1;
4361 debug_msg("player->textsink_linked set to 1\n");
4363 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" );
4366 debug_error("failed to get pad from sinkbin\n");
4370 mainbin = player->pipeline->mainbin;
4372 if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst)
4374 /* input selector */
4375 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
4376 if ( !text_selector )
4378 debug_error ( "failed to create subtitle input selector element\n" );
4381 g_object_set (text_selector, "sync-streams", TRUE, NULL);
4383 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
4384 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
4387 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_READY))
4389 debug_error("failed to set state(READY) to sinkbin\n");
4393 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector))
4395 debug_warning("failed to add subtitle input selector\n");
4399 debug_log ("created element input-selector");
4404 debug_log ("already having subtitle input selector");
4405 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
4410 if (!player->textsink_linked)
4412 debug_log("re-using textbin\n");
4415 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
4417 player->textsink_linked = 1;
4418 debug_msg("player->textsink_linked set to 1\n");
4422 debug_log("ignoring internal subtutle since external subtitle is available");
4428 debug_warning("unknown type of elementary stream! ignoring it...\n");
4437 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
4439 debug_error("failed to set state(READY) to sinkbin\n");
4443 /* Added for multi audio support to avoid adding audio bin again*/
4445 if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
4447 debug_error("failed to add sinkbin to pipeline\n");
4454 GstPad *srcpad = NULL;
4456 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst,"src");
4459 debug_error ("failed to get source pad");
4463 /* link input selector & textbin */
4464 if (gst_pad_link(srcpad,sinkpad)!= 0)
4466 debug_warning("failed to link input selector and textbin ghost pad\n");
4470 sinkpad = gst_element_get_request_pad (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink0");
4471 if (sinkpad == NULL)
4473 debug_error ("failed to get request pad from input selector");;
4479 if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad))
4481 debug_error("failed to get pad from sinkbin\n");
4488 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (sinkbin, GST_STATE_PAUSED))
4490 debug_error("failed to set state(PLAYING) to sinkbin\n");
4496 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (text_selector, GST_STATE_PAUSED))
4498 debug_error("failed to set state(READY) to sinkbin\n");
4504 gst_object_unref (sinkpad);
4508 debug_log ("linking sink bin success\n");
4510 /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
4511 * streaming task. if the task blocked, then buffer will not flow to the next element
4512 * ( autoplugging element ). so this is special hack for streaming. please try to remove it
4514 /* dec stream count. we can remove fakesink if it's zero */
4515 if (player->num_dynamic_pad)
4516 player->num_dynamic_pad--;
4518 debug_log ("no more pads: %d stream count dec : %d (num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
4520 if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
4522 __mmplayer_pipeline_complete (NULL, player);
4525 /* FIXIT : please leave a note why this code is needed */
4526 if(MMPLAYER_IS_WFD_STREAMING( player ))
4528 player->no_more_pad = TRUE;
4533 MMPLAYER_FREEIF(caps_str);
4536 gst_caps_unref( caps );
4539 gst_object_unref(GST_OBJECT(sinkpad));
4541 /* flusing out new attributes */
4542 if ( mmf_attrs_commit ( attrs ) )
4544 debug_error("failed to comit attributes\n");
4551 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
4553 int pro_value = 0; // in the case of expection, default will be returned.
4554 int dest_angle = rotation_angle;
4555 int rotation_type = -1;
4556 #define ROTATION_USING_SINK 0
4557 #define ROTATION_USING_CUSTOM 1
4558 #define ROTATION_USING_FLIP 2
4560 return_val_if_fail(player, FALSE);
4561 return_val_if_fail(value, FALSE);
4562 return_val_if_fail(rotation_angle >= 0, FALSE);
4564 if (rotation_angle >= 360)
4566 dest_angle = rotation_angle - 360;
4569 /* chech if supported or not */
4570 if ( dest_angle % 90 )
4572 debug_log("not supported rotation angle = %d", rotation_angle);
4577 * xvimagesink only (A)
4578 * custom_convert - no xv (e.g. memsink, evasimagesink (B)
4579 * videoflip - avsysmemsink (C)
4581 if (player->set_mode.video_zc)
4583 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
4585 rotation_type = ROTATION_USING_CUSTOM;
4589 rotation_type = ROTATION_USING_SINK;
4594 int surface_type = 0;
4595 rotation_type = ROTATION_USING_FLIP;
4597 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
4598 debug_log("check display surface type attribute: %d", surface_type);
4600 if ((surface_type == MM_DISPLAY_SURFACE_X) ||
4601 (surface_type == MM_DISPLAY_SURFACE_EVAS && !strcmp(player->ini.videosink_element_evas, "evaspixmapsink")))
4603 rotation_type = ROTATION_USING_SINK;
4607 rotation_type = ROTATION_USING_FLIP; //C
4610 debug_log("using %d type for rotation", rotation_type);
4613 /* get property value for setting */
4614 switch(rotation_type)
4616 case ROTATION_USING_SINK: // xvimagesink, pixmap
4623 pro_value = 3; // clockwise 90
4629 pro_value = 1; // counter-clockwise 90
4634 case ROTATION_USING_CUSTOM:
4636 gchar *ename = NULL;
4637 ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4639 if (g_strrstr(ename, "fimcconvert"))
4646 pro_value = 90; // clockwise 90
4652 pro_value = 270; // counter-clockwise 90
4658 case ROTATION_USING_FLIP: // videoflip
4666 pro_value = 1; // clockwise 90
4672 pro_value = 3; // counter-clockwise 90
4679 debug_log("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
4687 _mmplayer_update_video_param(mm_player_t* player) // @
4689 MMHandleType attrs = 0;
4690 int surface_type = 0;
4691 int org_angle = 0; // current supported angle values are 0, 90, 180, 270
4693 int user_angle_type= 0;
4694 int rotation_value = 0;
4698 /* check video sinkbin is created */
4699 return_val_if_fail ( player &&
4701 player->pipeline->videobin &&
4702 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
4703 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4704 MM_ERROR_PLAYER_NOT_INITIALIZED );
4706 attrs = MMPLAYER_GET_ATTRS(player);
4709 debug_error("cannot get content attribute");
4710 return MM_ERROR_PLAYER_INTERNAL;
4713 /* update user roation */
4714 mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
4716 /* get angle with user type */
4717 switch(user_angle_type)
4719 case MM_DISPLAY_ROTATION_NONE:
4722 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
4725 case MM_DISPLAY_ROTATION_180:
4728 case MM_DISPLAY_ROTATION_270: // clockwise 90
4733 /* get original orientation */
4734 if (player->v_stream_caps)
4736 GstStructure *str = NULL;
4738 str = gst_caps_get_structure (player->v_stream_caps, 0);
4739 if ( !gst_structure_get_int (str, "orientation", &org_angle))
4741 debug_log ("missing 'orientation' field in video caps");
4745 debug_log("check user angle: %d, orientation: %d", user_angle, org_angle);
4747 /* check video stream callback is used */
4748 if(!player->set_mode.media_packet_video_stream && player->use_video_stream )
4750 if (player->set_mode.video_zc)
4752 gchar *ename = NULL;
4756 mm_attrs_get_int_by_name(attrs, "display_width", &width);
4757 mm_attrs_get_int_by_name(attrs, "display_height", &height);
4759 /* resize video frame with requested values for fimcconvert */
4760 ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
4762 if (ename && g_strrstr(ename, "fimcconvert"))
4765 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4768 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4770 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4771 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4773 /* get rotation value to set */
4774 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4776 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
4778 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
4783 debug_log("using video stream callback with memsink. player handle : [%p]", player);
4785 /* get rotation value to set */
4786 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4788 g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
4791 return MM_ERROR_NONE;
4794 /* update display surface */
4795 mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
4796 debug_log("check display surface type attribute: %d", surface_type);
4798 /* configuring display */
4799 switch ( surface_type )
4801 case MM_DISPLAY_SURFACE_X:
4803 /* ximagesink or xvimagesink */
4806 int display_method = 0;
4815 int force_aspect_ratio = 0;
4816 gboolean visible = TRUE;
4818 /* common case if using x surface */
4819 mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
4823 xwin_id = *(int*)xid;
4824 debug_log("set video param : xid %d", *(int*)xid);
4827 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
4832 /* FIXIT : is it error case? */
4833 debug_warning("still we don't have xid on player attribute. create it's own surface.");
4836 /* if xvimagesink */
4837 if (!strcmp(player->ini.videosink_element_x,"xvimagesink"))
4839 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
4840 mm_attrs_get_double_by_name(attrs, "display_zoom", &zoom);
4841 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4842 mm_attrs_get_int_by_name(attrs, "display_src_crop_x", &src_crop_x);
4843 mm_attrs_get_int_by_name(attrs, "display_src_crop_y", &src_crop_y);
4844 mm_attrs_get_int_by_name(attrs, "display_src_crop_width", &src_crop_w);
4845 mm_attrs_get_int_by_name(attrs, "display_src_crop_height", &src_crop_h);
4846 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
4847 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
4848 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
4849 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
4850 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4851 #define DEFAULT_DISPLAY_MODE 2 // TV only, PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN
4853 /* setting for cropping media source */
4854 if (src_crop_w && src_crop_h)
4856 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4857 "src-crop-x", src_crop_x,
4858 "src-crop-y", src_crop_y,
4859 "src-crop-w", src_crop_w,
4860 "src-crop-h", src_crop_h,
4864 /* setting for ROI mode */
4865 if (display_method == 5) // 5 for ROI mode
4868 mm_attrs_get_int_by_name(attrs, "display_roi_mode", &roi_mode);
4869 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4870 "dst-roi-mode", roi_mode,
4876 /* get rotation value to set,
4877 do not use org_angle because ROI mode in xvimagesink needs both a rotation value and an orientation value */
4878 __mmplayer_get_property_value_for_rotation(player, user_angle, &rotation_value);
4882 /* get rotation value to set */
4883 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4886 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4887 "force-aspect-ratio", force_aspect_ratio,
4888 "zoom", (float)zoom,
4889 "orientation", org_angle/90, // setting for orientation of media, it is used for ROI/ZOOM feature in xvimagesink
4890 "rotate", rotation_value,
4891 "handle-events", TRUE,
4892 "display-geometry-method", display_method,
4893 "draw-borders", FALSE,
4895 "display-mode", DEFAULT_DISPLAY_MODE,
4898 debug_log("set video param : zoom %lf, rotate %d, method %d visible %d", zoom, rotation_value, display_method, visible);
4899 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 );
4900 debug_log("set video param : force aspect ratio %d, display mode %d", force_aspect_ratio, DEFAULT_DISPLAY_MODE);
4904 case MM_DISPLAY_SURFACE_EVAS:
4906 void *object = NULL;
4908 gboolean visible = TRUE;
4909 int display_method = 0;
4911 /* common case if using evas surface */
4912 mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
4913 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
4914 mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
4915 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
4917 /* if evasimagesink */
4918 if (!strcmp(player->ini.videosink_element_evas,"evasimagesink"))
4922 /* if it is evasimagesink, we are not supporting rotation */
4923 if (user_angle_type!=MM_DISPLAY_ROTATION_NONE)
4925 mm_attrs_set_int_by_name(attrs, "display_rotation", MM_DISPLAY_ROTATION_NONE);
4926 if (mmf_attrs_commit (attrs)) /* return -1 if error */
4927 debug_error("failed to commit\n");
4928 debug_warning("unsupported feature");
4929 return MM_ERROR_NOT_SUPPORT_API;
4931 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4932 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4933 "evas-object", object,
4935 "display-geometry-method", display_method,
4936 "rotate", rotation_value,
4938 debug_log("set video param : method %d", display_method);
4939 debug_log("set video param : evas-object %x, visible %d", object, visible);
4940 debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
4944 debug_error("no evas object");
4945 return MM_ERROR_PLAYER_INTERNAL;
4949 /* if evasimagesink using converter */
4950 if (player->set_mode.video_zc && player->pipeline->videobin[MMPLAYER_V_CONV].gst)
4954 int no_scaling = !scaling;
4956 mm_attrs_get_int_by_name(attrs, "display_width", &width);
4957 mm_attrs_get_int_by_name(attrs, "display_height", &height);
4959 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
4960 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
4961 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
4965 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
4966 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
4967 "dst-width", 0, /* setting 0, output video width will be media src's width */
4968 "dst-height", 0, /* setting 0, output video height will be media src's height */
4973 /* scaling order to fimcconvert */
4976 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
4980 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
4982 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
4984 debug_log("set video param : display_evas_do_scaling %d", scaling);
4988 /* if evaspixmapsink */
4989 if (!strcmp(player->ini.videosink_element_evas,"evaspixmapsink"))
4993 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
4994 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4995 "evas-object", object,
4997 "display-geometry-method", display_method,
4998 "rotate", rotation_value,
5000 debug_log("set video param : method %d", display_method);
5001 debug_log("set video param : evas-object %x, visible %d", object, visible);
5002 debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
5006 debug_error("no evas object");
5007 return MM_ERROR_PLAYER_INTERNAL;
5010 int display_method = 0;
5015 int origin_size = !scaling;
5017 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
5018 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
5019 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
5020 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
5021 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
5023 /* get rotation value to set */
5024 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
5026 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5027 "origin-size", origin_size,
5028 "rotate", rotation_value,
5033 "display-geometry-method", display_method,
5036 debug_log("set video param : method %d", display_method);
5037 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
5038 roi_x, roi_y, roi_w, roi_h );
5039 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
5043 case MM_DISPLAY_SURFACE_X_EXT: /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
5045 void *pixmap_id_cb = NULL;
5046 void *pixmap_id_cb_user_data = NULL;
5047 int display_method = 0;
5048 gboolean visible = TRUE;
5050 /* if xvimagesink */
5051 if (strcmp(player->ini.videosink_element_x,"xvimagesink"))
5053 debug_error("videosink is not xvimagesink");
5054 return MM_ERROR_PLAYER_INTERNAL;
5057 /* get information from attributes */
5058 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
5059 mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
5060 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
5061 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
5065 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
5066 if (pixmap_id_cb_user_data)
5068 debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
5073 debug_error("failed to set pixmap-id-callback");
5074 return MM_ERROR_PLAYER_INTERNAL;
5076 /* get rotation value to set */
5077 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
5079 debug_log("set video param : rotate %d, method %d, visible %d", rotation_value, display_method, visible);
5081 /* set properties of videosink plugin */
5082 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5083 "display-geometry-method", display_method,
5084 "draw-borders", FALSE,
5086 "rotate", rotation_value,
5087 "pixmap-id-callback", pixmap_id_cb,
5088 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
5092 case MM_DISPLAY_SURFACE_NULL:
5101 return MM_ERROR_NONE;
5105 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
5107 GList* bucket = element_bucket;
5108 MMPlayerGstElement* element = NULL;
5109 MMPlayerGstElement* prv_element = NULL;
5110 gint successful_link_count = 0;
5114 return_val_if_fail(element_bucket, -1);
5116 prv_element = (MMPlayerGstElement*)bucket->data;
5117 bucket = bucket->next;
5119 for ( ; bucket; bucket = bucket->next )
5121 element = (MMPlayerGstElement*)bucket->data;
5123 if ( element && element->gst )
5125 if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
5127 debug_log("linking [%s] to [%s] success\n",
5128 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5129 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5130 successful_link_count ++;
5134 debug_log("linking [%s] to [%s] failed\n",
5135 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
5136 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
5141 prv_element = element;
5146 return successful_link_count;
5150 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
5152 GList* bucket = element_bucket;
5153 MMPlayerGstElement* element = NULL;
5154 int successful_add_count = 0;
5158 return_val_if_fail(element_bucket, 0);
5159 return_val_if_fail(bin, 0);
5161 for ( ; bucket; bucket = bucket->next )
5163 element = (MMPlayerGstElement*)bucket->data;
5165 if ( element && element->gst )
5167 if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
5169 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed\n",
5170 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
5171 GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
5174 successful_add_count ++;
5180 return successful_add_count;
5186 * This function is to create audio pipeline for playing.
5188 * @param player [in] handle of player
5190 * @return This function returns zero on success.
5192 * @see __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
5194 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
5195 x_bin[x_id].id = x_id;\
5196 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5197 if ( ! x_bin[x_id].gst )\
5199 debug_error("failed to create %s \n", x_factory);\
5203 #define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin, x_player) \
5204 x_bin[x_id].id = x_id;\
5205 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5206 if ( ! x_bin[x_id].gst )\
5208 debug_error("failed to create %s \n", x_factory);\
5213 if (x_player->ini.set_dump_element_flag)\
5214 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5216 if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\
5218 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed\n",\
5219 GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\
5220 GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\
5224 /* macro for code readability. just for sinkbin-creation functions */
5225 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
5228 x_bin[x_id].id = x_id;\
5229 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
5230 if ( ! x_bin[x_id].gst )\
5232 debug_error("failed to create %s \n", x_factory);\
5237 if (x_player->ini.set_dump_element_flag)\
5238 __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
5240 if ( x_add_bucket )\
5241 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
5246 * - Local playback : audiotp !audioconvert ! volume ! capsfilter ! audioeffect ! audioeffect_sec ! audiosink
5247 * - Streaming : audiotp !audioconvert !volume ! audiosink
5248 * - PCM extraction : audiotp !audioconvert ! audioresample ! capsfilter ! fakesink
5251 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
5253 MMPlayerGstElement* first_element = NULL;
5254 MMPlayerGstElement* audiobin = NULL;
5255 MMHandleType attrs = 0;
5257 GstPad *ghostpad = NULL;
5258 GList* element_bucket = NULL;
5259 gboolean link_audio_sink_now = TRUE;
5264 return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5267 audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
5270 debug_error("failed to allocate memory for audiobin\n");
5271 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5274 attrs = MMPLAYER_GET_ATTRS(player);
5277 audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
5278 audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
5279 if ( !audiobin[MMPLAYER_A_BIN].gst )
5281 debug_error("failed to create audiobin\n");
5286 player->pipeline->audiobin = audiobin;
5288 player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
5290 /* Adding audiotp plugin for reverse trickplay feature */
5291 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
5294 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
5297 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, player->ini.name_of_audio_resampler, "audio resampler", TRUE, player);
5299 if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output
5301 int dst_samplerate = 0;
5302 int dst_channels = 0;
5304 char *caps_str = NULL;
5305 GstCaps* caps = NULL;
5307 /* get conf. values */
5308 mm_attrs_multiple_get(player->attrs,
5310 "pcm_extraction_samplerate", &dst_samplerate,
5311 "pcm_extraction_channels", &dst_channels,
5312 "pcm_extraction_depth", &dst_depth,
5316 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
5317 caps = gst_caps_new_simple ("audio/x-raw-int",
5318 "rate", G_TYPE_INT, dst_samplerate,
5319 "channels", G_TYPE_INT, dst_channels,
5320 "depth", G_TYPE_INT, dst_depth,
5322 caps_str = gst_caps_to_string(caps);
5323 debug_log("new caps : %s\n", caps_str);
5325 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5328 gst_caps_unref( caps );
5329 MMPLAYER_FREEIF( caps_str );
5332 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
5335 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
5337 else // normal playback
5341 GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE = 0,
5342 GST_BASE_AUDIO_SINK_SLAVE_SKEW,
5343 GST_BASE_AUDIO_SINK_SLAVE_NONE
5344 } GstBaseAudioSinkSlaveMethod;
5346 //GstCaps* caps = NULL;
5349 /* for logical volume control */
5350 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
5351 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
5353 if (player->sound.mute)
5355 debug_log("mute enabled\n");
5356 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
5361 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
5362 caps = gst_caps_from_string( "audio/x-raw-int, "
5363 "endianness = (int) LITTLE_ENDIAN, "
5364 "signed = (boolean) true, "
5365 "width = (int) 16, "
5366 "depth = (int) 16" );
5367 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
5368 gst_caps_unref( caps );
5371 /* chech if multi-chennels */
5372 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)
5374 GstPad *srcpad = NULL;
5375 GstCaps *caps = NULL;
5377 if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src")))
5379 if ((caps = gst_pad_get_caps(srcpad)))
5381 //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5382 GstStructure *str = gst_caps_get_structure(caps, 0);
5384 gst_structure_get_int (str, "channels", &channels);
5385 gst_caps_unref(caps);
5387 gst_object_unref(srcpad);
5391 /* audio effect element. if audio effect is enabled */
5392 if ( (strcmp(player->ini.name_of_audio_effect, ""))
5394 && player->ini.use_audio_effect_custom)
5396 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.name_of_audio_effect, "audio effect filter", TRUE, player);
5398 debug_log("audio effect config. bypass = %d, effect type = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
5400 if ( (!player->bypass_audio_effect)
5401 && player->ini.use_audio_effect_custom)
5403 if ( MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type )
5405 if (!_mmplayer_audio_effect_custom_apply(player))
5407 debug_msg("apply audio effect(custom) setting success\n");
5412 if ( (strcmp(player->ini.name_of_audio_effect_sec, ""))
5413 && (player->set_mode.rich_audio) )
5415 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.name_of_audio_effect_sec, "audio effect filter", TRUE, player);
5418 if (!MMPLAYER_IS_RTSP_STREAMING(player))
5420 if (player->set_mode.rich_audio && channels <= 2)
5421 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VSP, "audiovsp", "x-speed", TRUE, player);
5424 /* create audio sink */
5425 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.name_of_audiosink, "audiosink", link_audio_sink_now, player);
5428 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */
5429 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_BASE_AUDIO_SINK_SLAVE_NONE, NULL);
5431 /* FIXIT : using system clock. isn't there another way? */
5432 if (player->videodec_linked)
5434 debug_log("provide clock for movie = %s", (player->ini.provide_clock_for_movie)?"audio_clock":"sys_clock");
5435 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_movie, NULL);
5439 debug_log("provide clock for music = %s", (player->ini.provide_clock_for_music)?"audio_clock":"sys_clock");
5440 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_music, NULL);
5443 if ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink") || g_strrstr(player->ini.name_of_audiosink, "pulsesink") )
5445 gint volume_type = 0;
5446 gint audio_route = 0;
5447 gint sound_priority = FALSE;
5448 gint route_path = 0;
5449 gint latency_mode = 0;
5450 gint close_handle = 0;
5453 * It should be set after player creation through attribute.
5454 * But, it can not be changed during playing.
5456 mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
5457 mm_attrs_get_int_by_name(attrs, "sound_route", &audio_route);
5458 mm_attrs_get_int_by_name(attrs, "sound_priority", &sound_priority);
5459 mm_attrs_get_int_by_name(attrs, "sound_spk_out_only", &route_path);
5460 mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
5462 if (player->sm.user_route_policy != 0) {
5463 route_path = player->sm.user_route_policy;
5466 g_object_set(audiobin[MMPLAYER_A_SINK].gst,
5467 "volumetype", volume_type,
5468 "audio-route", audio_route,
5469 "priority", sound_priority,
5470 "user-route", route_path,
5471 "latency", latency_mode,
5472 "close-handle-on-prepare", close_handle,
5475 debug_log("audiosink property status...volume type:%d, route:%d, priority=%d, user-route=%d, latency=%d, close-resource=%d\n",
5476 volume_type, audio_route, sound_priority, route_path, latency_mode, close_handle);
5479 /* Antishock can be enabled when player is resumed by soundCM.
5480 * But, it's not used in MMS, setting and etc.
5481 * Because, player start seems like late.
5483 __mmplayer_set_antishock( player , FALSE );
5486 __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
5488 /* adding created elements to bin */
5489 debug_log("adding created elements to bin\n");
5490 if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
5492 debug_error("failed to add elements\n");
5496 /* linking elements in the bucket by added order. */
5497 debug_log("Linking elements in the bucket by added order.\n");
5498 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5500 debug_error("failed to link elements\n");
5504 /* get first element's sinkpad for creating ghostpad */
5505 first_element = (MMPlayerGstElement *)element_bucket->data;
5507 pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5510 debug_error("failed to get pad from first element of audiobin\n");
5514 ghostpad = gst_ghost_pad_new("sink", pad);
5517 debug_error("failed to create ghostpad\n");
5521 if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
5523 debug_error("failed to add ghostpad to audiobin\n");
5527 gst_object_unref(pad);
5529 g_list_free(element_bucket);
5531 mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
5535 return MM_ERROR_NONE;
5539 debug_log("ERROR : releasing audiobin\n");
5542 gst_object_unref(GST_OBJECT(pad));
5545 gst_object_unref(GST_OBJECT(ghostpad));
5547 g_list_free( element_bucket );
5549 /* release element which are not added to bin */
5550 for ( i = 1; i < MMPLAYER_A_NUM; i++ ) /* NOTE : skip bin */
5552 if ( audiobin[i].gst )
5554 GstObject* parent = NULL;
5555 parent = gst_element_get_parent( audiobin[i].gst );
5559 gst_object_unref(GST_OBJECT(audiobin[i].gst));
5560 audiobin[i].gst = NULL;
5564 gst_object_unref(GST_OBJECT(parent));
5569 /* release audiobin with it's childs */
5570 if ( audiobin[MMPLAYER_A_BIN].gst )
5572 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
5575 MMPLAYER_FREEIF( audiobin );
5577 player->pipeline->audiobin = NULL;
5579 return MM_ERROR_PLAYER_INTERNAL;
5583 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
5585 mm_player_t* player = (mm_player_t*) u_data;
5589 data = GST_BUFFER_DATA(buffer);
5590 size = GST_BUFFER_SIZE(buffer);
5592 if (player->audio_stream_cb && size && data)
5593 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
5599 __mmplayer_video_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer user_data)
5601 GstCaps *caps = NULL;
5602 MMPlayerVideoStreamDataType stream;
5603 MMPlayerMPlaneImage *scmn_imgb = NULL;
5604 GstStructure *structure = NULL;
5605 unsigned int fourcc = 0;
5606 mm_player_t* player = (mm_player_t*)user_data;
5608 caps = gst_buffer_get_caps(buffer);
5610 debug_error( "Caps is NULL." );
5614 //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5616 /* clear stream data structure */
5617 memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType));
5619 structure = gst_caps_get_structure( caps, 0 );
5620 gst_structure_get_int(structure, "width", &(stream.width));
5621 gst_structure_get_int(structure, "height", &(stream.height));
5622 gst_structure_get_fourcc(structure, "format", &fourcc);
5623 stream.format = util_get_pixtype(fourcc);
5624 gst_caps_unref( caps );
5628 debug_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5629 GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
5632 if (stream.width == 0 || stream.height == 0) {
5633 debug_error("Wrong condition!!");
5637 /* set size and timestamp */
5638 stream.length_total = GST_BUFFER_SIZE(buffer);
5639 stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano sec -> mili sec */
5642 if (player->set_mode.video_zc
5643 && player->set_mode.media_packet_video_stream
5644 && GST_BUFFER_MALLOCDATA(buffer)) {
5645 scmn_imgb = (MMPlayerMPlaneImage *)GST_BUFFER_MALLOCDATA(buffer);
5650 /* copy pointer of tbm bo, stride, elevation */
5651 memcpy(stream.bo, scmn_imgb->bo, sizeof(void *) * MM_PLAYER_IMGB_MPLANE_MAX);
5652 memcpy(stream.stride, scmn_imgb->s, sizeof(int) * MM_PLAYER_IMGB_MPLANE_MAX);
5653 memcpy(stream.elevation, scmn_imgb->e, sizeof(int) * MM_PLAYER_IMGB_MPLANE_MAX);
5657 for (i = 0 ; i < BUFFER_MAX_PLANE_NUM ; i++) {
5658 debug_log("w %d, h %d, s %d, e %d, bo %p",
5659 scmn_imgb->w[i],scmn_imgb->h[i],scmn_imgb->s[i],scmn_imgb->e[i],
5661 if(scmn_imgb->bo[i])
5662 debug_log("bo size %d", tbm_bo_size(scmn_imgb->bo[i]));
5666 /* set gst buffer */
5667 stream.internal_buffer = buffer;
5669 stream.data = GST_BUFFER_DATA(buffer);
5672 if (player->video_stream_cb) {
5673 player->video_stream_cb(&stream, player->video_stream_cb_user_param);
5680 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket, gboolean use_video_stream)
5682 gchar* video_csc = "ffmpegcolorspace"; // default colorspace converter
5683 GList* element_bucket = *bucket;
5685 return_val_if_fail(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5689 if (!player->set_mode.media_packet_video_stream && use_video_stream)
5691 if (player->set_mode.video_zc && strlen(player->ini.name_of_video_converter) > 0)
5693 video_csc = player->ini.name_of_video_converter;
5696 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5697 debug_log("using video converter: %s", video_csc);
5699 if ( !player->set_mode.video_zc)
5701 GstStructure *str = NULL;
5702 gint width = 0; //width of video
5703 gint height = 0; //height of video
5704 GstCaps* video_caps = NULL;
5705 GstStructure *structure = NULL;
5707 /* rotator, scaler and capsfilter */
5708 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5709 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "video scaler", TRUE, player);
5710 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE, player);
5712 /* get video stream caps parsed by demuxer */
5713 str = gst_caps_get_structure (player->v_stream_caps, 0);
5716 debug_error("cannot get structure");
5720 mm_attrs_get_int_by_name(player->attrs, "display_width", &width);
5723 structure = gst_structure_new("video/x-raw-rgb", "width", G_TYPE_INT, width, NULL);
5726 mm_attrs_get_int_by_name(player->attrs, "display_height", &height);
5730 gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
5732 structure = gst_structure_new("video/x-raw-rgb", "height", G_TYPE_INT, height, NULL);
5736 if (width ||height) {
5737 video_caps = gst_caps_new_full(structure, NULL);
5738 gst_structure_free(structure);
5740 g_object_set (GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
5741 MMPLAYER_LOG_GST_CAPS_TYPE(video_caps);
5742 gst_caps_unref(video_caps);
5748 MMDisplaySurfaceType surface_type = MM_DISPLAY_SURFACE_NULL;
5749 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", (int *)&surface_type);
5751 if (player->set_mode.video_zc)
5753 if ( (surface_type == MM_DISPLAY_SURFACE_EVAS) && ( !strcmp(player->ini.videosink_element_evas, "evasimagesink")) )
5755 video_csc = player->ini.name_of_video_converter;
5763 if (video_csc && (strcmp(video_csc, "")))
5765 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5766 debug_log("using video converter: %s", video_csc);
5769 /* set video rotator */
5770 if ( !player->set_mode.video_zc )
5771 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5774 #if !defined(__arm__)
5775 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE, player);
5779 *bucket = element_bucket;
5781 return MM_ERROR_NONE;
5786 return MM_ERROR_PLAYER_INTERNAL;
5790 * This function is to create video pipeline.
5792 * @param player [in] handle of player
5793 * caps [in] src caps of decoder
5794 * surface_type [in] surface type for video rendering
5796 * @return This function returns zero on success.
5798 * @see __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5802 * - x surface (arm/x86) : xvimagesink
5803 * - evas surface (arm) : evaspixmapsink
5804 * fimcconvert ! evasimagesink
5805 * - evas surface (x86) : videoconvertor ! videoflip ! evasimagesink
5808 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5812 GList*element_bucket = NULL;
5813 MMPlayerGstElement* first_element = NULL;
5814 MMPlayerGstElement* videobin = NULL;
5815 gchar *videosink_element = NULL;
5819 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5822 videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5825 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5828 player->pipeline->videobin = videobin;
5830 attrs = MMPLAYER_GET_ATTRS(player);
5833 debug_error("cannot get content attribute");
5834 return MM_ERROR_PLAYER_INTERNAL;
5838 videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5839 videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5840 if ( !videobin[MMPLAYER_V_BIN].gst )
5842 debug_error("failed to create videobin");
5846 if( player->use_video_stream ) // video stream callback, so send raw video data to application
5848 debug_log("using memsink\n");
5850 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, TRUE) != MM_ERROR_NONE)
5853 /* finally, create video sink. output will be BGRA8888. */
5854 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE, player);
5856 MMPLAYER_SIGNAL_CONNECT( player,
5857 videobin[MMPLAYER_V_SINK].gst,
5858 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5860 G_CALLBACK(__mmplayer_videostream_cb),
5863 else // render video data using sink plugin like xvimagesink
5865 if ( __mmplayer_gst_create_video_filters(player, &element_bucket, FALSE) != MM_ERROR_NONE)
5868 /* set video sink */
5869 switch (surface_type)
5871 case MM_DISPLAY_SURFACE_X:
5872 if (strlen(player->ini.videosink_element_x) > 0)
5873 videosink_element = player->ini.videosink_element_x;
5877 case MM_DISPLAY_SURFACE_EVAS:
5878 if (strlen(player->ini.videosink_element_evas) > 0)
5879 videosink_element = player->ini.videosink_element_evas;
5883 case MM_DISPLAY_SURFACE_X_EXT:
5885 void *pixmap_id_cb = NULL;
5886 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
5887 if (pixmap_id_cb) /* this is used for the videoTextue(canvasTexture) overlay */
5889 videosink_element = player->ini.videosink_element_x;
5893 debug_error("something wrong.. callback function for getting pixmap id is null");
5898 case MM_DISPLAY_SURFACE_NULL:
5899 if (strlen(player->ini.videosink_element_fake) > 0)
5900 videosink_element = player->ini.videosink_element_fake;
5905 debug_error("unidentified surface type");
5909 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE, player);
5910 debug_log("selected videosink name: %s", videosink_element);
5911 if(surface_type==MM_DISPLAY_SURFACE_X)
5913 MMPLAYER_SIGNAL_CONNECT( player,
5914 videobin[MMPLAYER_V_SINK].gst,
5915 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5917 G_CALLBACK(__mmplayer_display_status_cb),
5919 MMPLAYER_SIGNAL_CONNECT( player,
5920 videobin[MMPLAYER_V_SINK].gst,
5921 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5922 "external-resolution",
5923 G_CALLBACK(__mmplayer_external_resolution_cb),
5925 MMPLAYER_SIGNAL_CONNECT( player,
5926 videobin[MMPLAYER_V_SINK].gst,
5927 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5929 G_CALLBACK(__mmplayer_hided_window_cb),
5931 MMPLAYER_SIGNAL_CONNECT( player,
5932 videobin[MMPLAYER_V_SINK].gst,
5933 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5935 G_CALLBACK(__mmplayer_quick_panel_on_cb),
5937 MMPLAYER_SIGNAL_CONNECT( player,
5938 videobin[MMPLAYER_V_SINK].gst,
5939 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5940 "multiwindow-active",
5941 G_CALLBACK(__mmplayer_multiwindow_active_cb),
5944 /* connect signal handlers for sink plug-in */
5945 switch (surface_type) {
5946 case MM_DISPLAY_SURFACE_X_EXT:
5947 MMPLAYER_SIGNAL_CONNECT( player,
5948 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5949 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5950 "frame-render-error",
5951 G_CALLBACK(__mmplayer_videoframe_render_error_cb),
5953 debug_log("videoTexture usage, connect a signal handler for pixmap rendering error");
5960 if ( _mmplayer_update_video_param(player) != MM_ERROR_NONE)
5963 /* store it as it's sink element */
5964 __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
5966 /* adding created elements to bin */
5967 if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
5969 debug_error("failed to add elements\n");
5973 /* Linking elements in the bucket by added order */
5974 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
5976 debug_error("failed to link elements\n");
5980 /* get first element's sinkpad for creating ghostpad */
5981 first_element = (MMPlayerGstElement *)element_bucket->data;
5982 if ( !first_element )
5984 debug_error("failed to get first element from bucket\n");
5988 pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5991 debug_error("failed to get pad from first element\n");
5995 /* create ghostpad */
5996 player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5997 if ( FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
5999 debug_error("failed to add ghostpad to videobin\n");
6002 gst_object_unref(pad);
6004 /* done. free allocated variables */
6005 g_list_free(element_bucket);
6007 mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
6011 return MM_ERROR_NONE;
6014 debug_error("ERROR : releasing videobin\n");
6016 g_list_free( element_bucket );
6019 gst_object_unref(GST_OBJECT(pad));
6021 /* release videobin with it's childs */
6022 if ( videobin[MMPLAYER_V_BIN].gst )
6024 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
6028 MMPLAYER_FREEIF( videobin );
6030 player->pipeline->videobin = NULL;
6032 return MM_ERROR_PLAYER_INTERNAL;
6035 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
6037 GList *element_bucket = NULL;
6038 MMPlayerGstElement *textbin = player->pipeline->textbin;
6040 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_f_queue", TRUE, player);
6041 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6042 MMPLAYER_SIGNAL_CONNECT( player,
6043 G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6044 MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6046 G_CALLBACK(__mmplayer_update_subtitle),
6049 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
6050 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6051 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6053 if (!player->play_subtitle)
6055 debug_log ("add textbin sink as sink element of whole pipeline.\n");
6056 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6059 /* adding created elements to bin */
6060 debug_log("adding created elements to bin\n");
6061 if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6063 debug_error("failed to add elements\n");
6067 /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6068 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_IS_SINK);
6069 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_IS_SINK);
6071 /* linking elements in the bucket by added order. */
6072 debug_log("Linking elements in the bucket by added order.\n");
6073 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
6075 debug_error("failed to link elements\n");
6079 /* done. free allocated variables */
6080 g_list_free(element_bucket);
6082 if (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst)
6085 GstPad *ghostpad = NULL;
6087 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst), "sink");
6090 debug_error("failed to get video pad of textbin\n");
6091 return MM_ERROR_PLAYER_INTERNAL;
6094 ghostpad = gst_ghost_pad_new("text_sink", pad);
6095 gst_object_unref(pad);
6099 debug_error("failed to create ghostpad of textbin\n");
6103 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6105 debug_error("failed to add ghostpad to textbin\n");
6110 return MM_ERROR_NONE;
6113 g_list_free(element_bucket);
6115 return MM_ERROR_PLAYER_INTERNAL;
6118 static int __mmplayer_gst_create_text_pipeline(mm_player_t* player)
6120 MMPlayerGstElement *textbin = NULL;
6121 GList *element_bucket = NULL;
6123 GstPad *ghostpad = NULL;
6128 return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6131 textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
6134 debug_error("failed to allocate memory for textbin\n");
6135 return MM_ERROR_PLAYER_NO_FREE_SPACE;
6139 textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
6140 textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
6141 if ( !textbin[MMPLAYER_T_BIN].gst )
6143 debug_error("failed to create textbin\n");
6148 player->pipeline->textbin = textbin;
6151 if (player->use_textoverlay)
6153 debug_log ("use textoverlay for displaying \n");
6155 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_TEXT_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst, player);
6157 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst, player);
6159 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst, player);
6161 MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst, player);
6163 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink"))
6165 debug_error("failed to link queue and converter\n");
6169 if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink"))
6171 debug_error("failed to link queue and textoverlay\n");
6175 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink"))
6177 debug_error("failed to link queue and textoverlay\n");
6181 if (textbin[MMPLAYER_T_TEXT_QUEUE].gst)
6183 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_QUEUE].gst), "sink");
6186 debug_error("failed to get src pad of textbin\n");
6190 ghostpad = gst_ghost_pad_new("sink", pad);
6193 debug_error("failed to create ghostpad of textbin\n");
6197 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad))
6199 debug_error("failed to add ghostpad to textbin\n");
6206 int surface_type = 0;
6207 GstCaps* caps = NULL;
6209 debug_log ("use subtitle message for displaying \n");
6211 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
6213 switch(surface_type)
6215 case MM_DISPLAY_SURFACE_X:
6217 /* check whether external subtitle supported or not */
6218 if (!player->ini.external_subtitle)
6220 debug_log ("not supported external subtitle\n");
6221 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6223 debug_error("failed to make plain text elements\n");
6229 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEE, "tee", "text_tee", TRUE, player);
6230 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_QUEUE, "queue", "text_f_queue", TRUE, player);
6231 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst),
6232 "max-size-time", (guint64)0,
6233 "max-size-bytes", (guint)0,
6234 "max-size-buffers", (guint)5,
6237 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_FAKE_IDENTITY, "identity", "text_f_identity", TRUE, player);
6238 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "signal-handoffs", FALSE, NULL);
6240 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
6241 MMPLAYER_SIGNAL_CONNECT( player,
6242 G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
6243 MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
6245 G_CALLBACK(__mmplayer_update_subtitle),
6248 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", FALSE, NULL);
6249 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
6250 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
6252 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_QUEUE, "queue", "text_queue", TRUE, player);
6253 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_QUEUE].gst),
6254 "max-size-time", (guint64)0,
6255 "max-size-bytes", (guint)0,
6256 "max-size-buffers", (guint)5,
6259 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_IDENTITY, "identity", "text_identity", TRUE, player);
6260 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "signal-handoffs", FALSE, NULL);
6262 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_RENDER, "subrender", "text_subrender", TRUE, player);
6264 if (player->font_desc == NULL)
6265 g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "font-desc", "Tizen 42", NULL);
6267 g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "font-desc", player->font_desc, NULL);
6269 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "font-color", player->font_color, NULL);
6270 g_object_set (G_OBJECT (player->pipeline->textbin[MMPLAYER_T_RENDER].gst), "font-bg-color", player->font_bg_color, NULL);
6272 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_CAPSFILTER, "capsfilter", "text_capsfilter", TRUE, player);
6273 caps = gst_caps_from_string( "video/x-raw-rgb, "
6274 "width = (int) [ 1, MAX ], "
6275 "height = (int) [ 1, MAX ], "
6276 "framerate = (fraction) [ 0, MAX ], "
6277 "subtitle = (boolean) true" );
6278 g_object_set (G_OBJECT(textbin[MMPLAYER_T_CAPSFILTER].gst), "caps", caps, NULL );
6279 gst_caps_unref( caps );
6280 MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_VIDEO_SINK, "xvimagesink", "text_xvimagesink", TRUE, player);
6281 g_object_set(G_OBJECT(textbin[MMPLAYER_T_VIDEO_SINK].gst), "subpicture", TRUE, NULL);
6283 player->display_stat = util_get_is_connected_external_display();
6285 if(player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE)
6287 g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "external-width", player->ini.mirroring_width, NULL);
6288 g_object_set (G_OBJECT (textbin[MMPLAYER_T_RENDER].gst), "external-height", player->ini.mirroring_height, NULL);
6289 g_object_set (G_OBJECT (textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-width", player->ini.mirroring_width, NULL);
6290 g_object_set (G_OBJECT (textbin[MMPLAYER_T_VIDEO_SINK].gst), "external-height", player->ini.mirroring_height, NULL);
6292 g_object_set(G_OBJECT(textbin[MMPLAYER_T_VIDEO_SINK].gst), "show-preroll-frame", FALSE, NULL);
6294 /* if connected with external display */
6295 if ((player->display_stat == MMPLAYER_DISPLAY_STATUS_HDMI_ACTIVE) ||
6296 (player->display_stat == MMPLAYER_DISPLAY_STATUS_UNKNOWN_ACTIVE)) {
6297 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL);
6298 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
6299 debug_warning ("connected with external display");
6301 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst), "drop-probability", (gfloat)0.0, NULL);
6302 g_object_set (G_OBJECT (textbin[MMPLAYER_T_TEXT_IDENTITY].gst), "drop-probability", (gfloat)1.0, NULL);
6303 g_object_set(G_OBJECT(textbin[MMPLAYER_T_VIDEO_SINK].gst), "async", FALSE, NULL);
6304 g_object_set (G_OBJECT (textbin[MMPLAYER_T_FAKE_SINK].gst), "async", FALSE, NULL);
6306 debug_warning ("non-connected status");
6308 if (!player->play_subtitle)
6310 debug_log ("add textbin sink as sink element of whole pipeline.\n");
6311 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
6312 __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_VIDEO_SINK].gst));
6315 /* adding created elements to bin */
6316 if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
6318 debug_error("failed to add elements\n");
6322 /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
6323 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_IS_SINK);
6324 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_IS_SINK);
6325 GST_OBJECT_FLAG_UNSET (textbin[MMPLAYER_T_VIDEO_SINK].gst, GST_ELEMENT_IS_SINK);
6327 /* linking elements in the bucket by added order. */
6330 rpad = gst_element_get_request_pad(textbin[MMPLAYER_T_TEE].gst, "src%d");
6331 pad = gst_element_get_static_pad(textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst, "sink");
6332 gst_pad_link(rpad, pad);
6333 gst_object_unref(rpad);
6334 gst_object_unref(pad);
6336 rpad = gst_element_get_request_pad(textbin[MMPLAYER_T_TEE].gst, "src%d");
6337 pad = gst_element_get_static_pad(textbin[MMPLAYER_T_TEXT_QUEUE].gst, "sink");
6338 gst_pad_link(rpad, pad);
6339 gst_object_unref(rpad);
6340 gst_object_unref(pad);
6342 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_FAKE_QUEUE].gst, "src", textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "sink")) {
6343 debug_error ("fake queue and identity could not be linked.\n");
6346 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_FAKE_IDENTITY].gst, "src", textbin[MMPLAYER_T_FAKE_SINK].gst, "sink")) {
6347 debug_error ("indentity and fake sink could not be linked.\n");
6350 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_QUEUE].gst, "src", textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "sink")) {
6351 debug_error ("queue and identity could not be linked.\n");
6354 if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_IDENTITY].gst, "src", textbin[MMPLAYER_T_RENDER].gst, "sink")) {
6355 debug_error ("identity and subrender could not be linked.\n");
6358 if (!gst_element_link_pads (textbin[MMPLAYER_T_RENDER].gst, "src", textbin[MMPLAYER_T_CAPSFILTER].gst, "sink")) {
6359 debug_error ("subrender and capsfilter could not be linked.\n");
6362 if (!gst_element_link_pads (textbin[MMPLAYER_T_CAPSFILTER].gst, "src", textbin[MMPLAYER_T_VIDEO_SINK].gst, "sink")) {
6363 debug_error ("capsfilter and xvimagesink could not be linked.\n");
6367 /* done. free allocated variables */
6368 g_list_free(element_bucket);
6369 if (textbin[MMPLAYER_T_TEE].gst)
6371 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEE].gst), "sink");
6374 debug_error("failed to get text pad of textbin\n");
6378 ghostpad = gst_ghost_pad_new("text_sink", pad);
6381 debug_error("failed to create ghostpad of textbin\n");
6385 if ( FALSE == gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad) )
6387 debug_error("failed to add ghostpad to textbin\n");
6395 case MM_DISPLAY_SURFACE_EVAS:
6396 case MM_DISPLAY_SURFACE_GL:
6397 case MM_DISPLAY_SURFACE_NULL:
6398 case MM_DISPLAY_SURFACE_X_EXT:
6399 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE)
6401 debug_error("failed to make plain text elements\n");
6410 gst_object_unref(pad);
6414 return MM_ERROR_NONE;
6418 debug_log("ERROR : releasing textbin\n");
6421 gst_object_unref(GST_OBJECT(pad));
6424 gst_object_unref(GST_OBJECT(ghostpad));
6426 g_list_free( element_bucket );
6428 /* release element which are not added to bin */
6429 for ( i = 1; i < MMPLAYER_T_NUM; i++ ) /* NOTE : skip bin */
6431 if ( textbin[i].gst )
6433 GstObject* parent = NULL;
6434 parent = gst_element_get_parent( textbin[i].gst );
6438 gst_object_unref(GST_OBJECT(textbin[i].gst));
6439 textbin[i].gst = NULL;
6443 gst_object_unref(GST_OBJECT(parent));
6448 /* release textbin with it's childs */
6449 if ( textbin[MMPLAYER_T_BIN].gst )
6451 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
6454 MMPLAYER_FREEIF( textbin );
6456 player->pipeline->textbin = NULL;
6458 return MM_ERROR_PLAYER_INTERNAL;
6463 __mmplayer_gst_create_subtitle_src(mm_player_t* player)
6465 MMPlayerGstElement* mainbin = NULL;
6466 MMHandleType attrs = 0;
6467 GstElement *subsrc = NULL;
6468 GstElement *subparse = NULL;
6469 gchar *subtitle_uri =NULL;
6470 const gchar *charset = NULL;
6471 GstPad *sinkpad = NULL;
6472 GstPad *srcpad = NULL;
6478 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6480 mainbin = player->pipeline->mainbin;
6482 attrs = MMPLAYER_GET_ATTRS(player);
6485 debug_error("cannot get content attribute\n");
6486 return MM_ERROR_PLAYER_INTERNAL;
6489 mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
6490 if ( !subtitle_uri || strlen(subtitle_uri) < 1)
6492 debug_error("subtitle uri is not proper filepath.\n");
6493 return MM_ERROR_PLAYER_INVALID_URI;
6495 debug_log("subtitle file path is [%s].\n", subtitle_uri);
6498 /* create the subtitle source */
6499 subsrc = gst_element_factory_make("filesrc", "subtitle_source");
6502 debug_error ( "failed to create filesrc element\n" );
6505 g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL);
6507 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6508 mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
6510 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc))
6512 debug_warning("failed to add queue\n");
6517 subparse = gst_element_factory_make("submux", "external-submux");
6520 debug_error ( "failed to create subparse element\n" );
6524 charset = util_get_charset(subtitle_uri);
6527 debug_log ("detected charset is %s\n", charset );
6528 g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL);
6531 mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].id = MMPLAYER_M_T_SUBMUX_EXTERNAL;
6532 mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst = subparse;
6534 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse))
6536 debug_warning("failed to add subparse\n");
6539 sinkpad = gst_element_get_request_pad (subparse, "sink%d");
6540 srcpad = gst_element_get_pad(subsrc,"src");
6542 /* link filesrc & submux */
6543 if (gst_pad_link (srcpad, sinkpad) != 0)
6545 debug_warning("failed to link subsrc and subparse\n");
6549 player->play_subtitle = TRUE;
6550 player->adjust_subtitle_pos = 0;
6552 debug_log ("play subtitle using subtitle file\n");
6554 if (player->pipeline->textbin == NULL)
6556 /* if textbin is null, assuming input selector also not created */
6557 GstElement *selector = NULL;
6559 /* input selector */
6560 selector = gst_element_factory_make("input-selector", "subtitle_inselector");
6563 debug_error ( "failed to create subtitle input selector element\n" );
6566 g_object_set (selector, "sync-streams", TRUE, NULL);
6568 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
6569 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = selector;
6571 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector))
6573 debug_warning("failed to add subtitle input selector\n");
6577 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
6579 debug_error("failed to create textbin. continuing without text\n");
6583 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst)))
6585 debug_warning("failed to add textbin\n");
6589 debug_log ("link text input selector and textbin ghost pad");
6590 if (!gst_element_link_pads (mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink"))
6592 debug_warning("failed to link subparse and textbin\n");
6596 sinkpad = gst_element_get_request_pad (mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink%d");
6597 if (sinkpad == NULL)
6599 debug_error ("failed to get request pad");;
6603 debug_log ("Set Active Pad - %s\n", GST_DEBUG_PAD_NAME(sinkpad));
6604 g_object_set (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "active-pad", sinkpad, NULL);
6606 player->textsink_linked = 1;
6607 player->external_text_idx = 0;
6608 debug_msg("player->textsink_linked set to 1\n");
6612 debug_log("text bin has been created. reuse it.");
6614 sinkpad = gst_element_get_request_pad (mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink%d");
6615 if (sinkpad == NULL)
6617 debug_error ("failed to get request pad");;
6621 player->external_text_idx = 1;
6624 srcpad = gst_element_get_pad (subparse,"src");
6626 /* link submux & input selector */
6627 if (gst_pad_link (srcpad, sinkpad) != 0)
6629 debug_warning("failed to link submux and input selector\n");
6633 pad = gst_element_get_static_pad (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
6637 debug_error("failed to get sink pad from textsink to probe data");
6638 return MM_ERROR_PLAYER_INTERNAL;
6641 gst_pad_add_buffer_probe(pad, G_CALLBACK(__mmplayer_subtitle_adjust_position_probe), player);
6642 gst_object_unref(pad);
6648 return MM_ERROR_NONE;
6651 return MM_ERROR_PLAYER_INTERNAL;
6655 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
6657 mm_player_t* player = (mm_player_t*) data;
6658 MMMessageParamType msg = {0, };
6659 GstClockTime duration = 0;
6660 guint8 *text = NULL;
6661 guint text_size = 0;
6662 gboolean ret = TRUE;
6666 return_val_if_fail ( player, FALSE );
6667 return_val_if_fail ( buffer, FALSE );
6669 text = GST_BUFFER_DATA(buffer);
6670 text_size = GST_BUFFER_SIZE(buffer);
6671 duration = GST_BUFFER_DURATION(buffer);
6673 if ( player->set_mode.subtitle_off )
6675 debug_log("subtitle is OFF.\n" );
6679 if ( !text || (text_size == 0))
6681 debug_log("There is no subtitle to be displayed.\n" );
6685 msg.data = (void *) text;
6686 msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
6688 debug_log("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
6690 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
6698 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstBuffer *buffer, gpointer u_data)
6700 mm_player_t *player = (mm_player_t *) u_data;
6701 GstClockTime cur_timestamp = 0;
6702 gint64 adjusted_timestamp = 0;
6704 return_val_if_fail ( player, FALSE );
6705 return_val_if_fail ( buffer, FALSE );
6707 if ( player->set_mode.subtitle_off )
6709 debug_log("subtitle is OFF.\n" );
6713 if (player->adjust_subtitle_pos == 0 )
6715 debug_log("nothing to do");
6719 cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
6721 adjusted_timestamp = (gint64) cur_timestamp + ((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
6723 if ( adjusted_timestamp < 0)
6725 debug_log("adjusted_timestamp under zero");
6730 GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
6731 debug_log("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
6732 GST_TIME_ARGS(cur_timestamp),
6733 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
6737 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
6741 /* check player and subtitlebin are created */
6742 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6743 return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API );
6747 debug_log ("nothing to do\n");
6749 return MM_ERROR_NONE;
6754 case MM_PLAYER_POS_FORMAT_TIME:
6756 /* check current postion */
6757 player->adjust_subtitle_pos = position;
6759 debug_log("save adjust_subtitle_pos in player") ;
6765 debug_warning("invalid format.\n");
6767 return MM_ERROR_INVALID_ARGUMENT;
6773 return MM_ERROR_NONE;
6777 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
6779 GstElement *appsrc = element;
6780 tBuffer *buf = (tBuffer *)user_data;
6781 GstBuffer *buffer = NULL;
6782 GstFlowReturn ret = GST_FLOW_OK;
6785 return_if_fail ( element );
6786 return_if_fail ( buf );
6788 buffer = gst_buffer_new ();
6792 if (buf->offset >= buf->len)
6794 debug_log("call eos appsrc\n");
6795 g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
6799 if ( buf->len - buf->offset < size)
6801 len = buf->len - buf->offset + buf->offset;
6804 GST_BUFFER_DATA(buffer) = (guint8*)(buf->buf + buf->offset);
6805 GST_BUFFER_SIZE(buffer) = len;
6806 GST_BUFFER_OFFSET(buffer) = buf->offset;
6807 GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
6809 //debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
6810 g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
6816 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
6818 tBuffer *buf = (tBuffer *)user_data;
6820 return_val_if_fail ( buf, FALSE );
6822 buf->offset = (int)size;
6828 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
6830 mm_player_t *player = (mm_player_t*)user_data;
6832 return_if_fail ( player );
6834 debug_msg("app-src: feed data\n");
6836 if(player->need_data_cb)
6837 player->need_data_cb(size, player->buffer_cb_user_param);
6841 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
6843 mm_player_t *player = (mm_player_t*)user_data;
6845 return_val_if_fail ( player, FALSE );
6847 debug_msg("app-src: seek data\n");
6849 if(player->seek_data_cb)
6850 player->seek_data_cb(offset, player->buffer_cb_user_param);
6857 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
6859 mm_player_t *player = (mm_player_t*)user_data;
6861 return_val_if_fail ( player, FALSE );
6863 debug_msg("app-src: enough data:%p\n", player->enough_data_cb);
6865 if(player->enough_data_cb)
6866 player->enough_data_cb(player->buffer_cb_user_param);
6872 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
6874 mm_player_t* player = (mm_player_t*)hplayer;
6875 GstBuffer *buffer = NULL;
6876 GstFlowReturn gst_ret = GST_FLOW_OK;
6877 int ret = MM_ERROR_NONE;
6881 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6883 /* check current state */
6884 // MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6887 /* NOTE : we should check and create pipeline again if not created as we destroy
6888 * whole pipeline when stopping in streamming playback
6890 if ( ! player->pipeline )
6892 if ( MM_ERROR_NONE != __gst_realize( player ) )
6894 debug_error("failed to realize before starting. only in streamming\n");
6895 return MM_ERROR_PLAYER_INTERNAL;
6899 debug_msg("app-src: pushing data\n");
6903 debug_error("buf is null\n");
6904 return MM_ERROR_NONE;
6907 buffer = gst_buffer_new ();
6909 return MM_ERROR_PLAYER_INTERNAL;
6913 debug_log("call eos appsrc\n");
6914 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
6915 return MM_ERROR_NONE;
6918 GST_BUFFER_DATA(buffer) = (guint8*)(buf);
6919 GST_BUFFER_SIZE(buffer) = size;
6921 debug_log("feed buffer %p, length %u\n", buf, size);
6922 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
6929 /* if retval is FALSE, it will be dropped for perfomance. */
6931 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
6933 gboolean retval = FALSE;
6935 if ( !(player->pipeline && player->pipeline->mainbin) )
6937 debug_error("player pipeline handle is null");
6941 switch (GST_MESSAGE_TYPE (message))
6943 case GST_MESSAGE_TAG:
6944 case GST_MESSAGE_EOS:
6945 case GST_MESSAGE_ERROR:
6946 case GST_MESSAGE_WARNING:
6947 case GST_MESSAGE_CLOCK_LOST:
6948 case GST_MESSAGE_NEW_CLOCK:
6949 case GST_MESSAGE_ELEMENT:
6950 case GST_MESSAGE_DURATION:
6951 case GST_MESSAGE_ASYNC_START:
6954 case GST_MESSAGE_ASYNC_DONE:
6955 case GST_MESSAGE_STATE_CHANGED:
6956 /* we only handle messages from pipeline */
6957 if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->pp_rebuilding))
6962 case GST_MESSAGE_BUFFERING:
6964 gint buffer_percent = 0;
6966 gst_message_parse_buffering (message, &buffer_percent);
6968 if ((MMPLAYER_IS_STREAMING(player)) &&
6969 (player->streamer) &&
6970 (player->streamer->is_buffering == TRUE) &&
6971 (buffer_percent == MAX_BUFFER_PERCENT))
6973 debug_log (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
6974 player->streamer->is_buffering_done = TRUE;
6988 static GstBusSyncReply
6989 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
6991 mm_player_t *player = (mm_player_t *)data;
6992 GstBusSyncReply reply = GST_BUS_DROP;
6994 if ( ! ( player->pipeline && player->pipeline->mainbin ) )
6996 debug_error("player pipeline handle is null");
6997 return GST_BUS_PASS;
7000 if (!__mmplayer_check_useful_message(player, message))
7002 gst_message_unref (message);
7003 return GST_BUS_DROP;
7006 switch (GST_MESSAGE_TYPE (message))
7008 case GST_MESSAGE_STATE_CHANGED:
7009 /* post directly for fast launch */
7010 if (player->sync_handler) {
7011 __mmplayer_gst_callback(NULL, message, player);
7012 reply = GST_BUS_DROP;
7015 reply = GST_BUS_PASS;
7018 case GST_MESSAGE_TAG:
7019 __mmplayer_gst_extract_tag_from_msg(player, message);
7021 case GST_MESSAGE_DURATION:
7022 __mmplayer_gst_handle_duration(player, message);
7024 case GST_MESSAGE_ASYNC_DONE:
7025 /* NOTE:Don't call gst_callback directly
7026 * because previous frame can be showed even though this message is received for seek.
7029 reply = GST_BUS_PASS;
7033 if (reply == GST_BUS_DROP)
7034 gst_message_unref (message);
7040 * This function is to create audio or video pipeline for playing.
7042 * @param player [in] handle of player
7044 * @return This function returns zero on success.
7049 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
7052 MMPlayerGstElement *mainbin = NULL;
7053 MMHandleType attrs = 0;
7054 GstElement* element = NULL;
7055 GList* element_bucket = NULL;
7056 gboolean need_state_holder = TRUE;
7061 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7063 /* get profile attribute */
7064 attrs = MMPLAYER_GET_ATTRS(player);
7067 debug_error("cannot get content attribute\n");
7071 /* create pipeline handles */
7072 if ( player->pipeline )
7074 debug_warning("pipeline should be released before create new one\n");
7078 player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
7079 if (player->pipeline == NULL)
7082 memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
7085 /* create mainbin */
7086 mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
7087 if (mainbin == NULL)
7090 memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
7092 /* create pipeline */
7093 mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
7094 mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
7095 if ( ! mainbin[MMPLAYER_M_PIPE].gst )
7097 debug_error("failed to create pipeline\n");
7100 player->demux_pad_index = 0;
7101 player->subtitle_language_list = NULL;
7103 player->font_color = player->ini.font_color;
7104 player->font_bg_color = player->ini.font_background_color;
7106 player->display_stat = MMPLAYER_DISPLAY_STATUS_NULL;
7107 player->is_subtitle_force_drop = FALSE;
7108 player->last_multiwin_status = FALSE;
7110 /* create source element */
7111 switch ( player->profile.uri_type )
7113 /* rtsp streamming */
7114 case MM_PLAYER_URI_TYPE_URL_RTSP:
7116 gint network_bandwidth;
7117 gchar *user_agent, *wap_profile;
7119 element = gst_element_factory_make(player->ini.name_of_rtspsrc, "streaming_source");
7123 debug_error("failed to create streaming source element\n");
7127 debug_log("using streamming source [%s].\n", player->ini.name_of_rtspsrc);
7130 network_bandwidth = 0;
7131 user_agent = wap_profile = NULL;
7134 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7135 mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
7136 mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
7138 secure_debug_log("user_agent : %s\n", user_agent);
7139 secure_debug_log("wap_profile : %s\n", wap_profile);
7140 debug_log("network_bandwidth : %d\n", network_bandwidth);
7141 debug_log("buffering time : %d\n", player->ini.rtsp_buffering_time);
7142 debug_log("rebuffering time : %d\n", player->ini.rtsp_rebuffering_time);
7144 /* setting property to streaming source */
7145 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7146 g_object_set(G_OBJECT(element), "bandwidth", network_bandwidth, NULL);
7147 g_object_set(G_OBJECT(element), "buffering_time", player->ini.rtsp_buffering_time, NULL);
7148 g_object_set(G_OBJECT(element), "rebuffering_time", player->ini.rtsp_rebuffering_time, NULL);
7150 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7152 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
7154 MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7155 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
7156 MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
7157 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
7159 player->use_decodebin = FALSE;
7163 /* WFD streamming */
7164 case MM_PLAYER_URI_TYPE_URL_WFD:
7166 element = gst_element_factory_make("wfdrtspsrc", "wfd_source");
7169 debug_error("failed to create wfd streaming source element\n");
7172 debug_log("using wfd streamming source wfdrtspsrc.\n");
7173 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7174 g_object_set(G_OBJECT(element), "debug", TRUE, NULL);
7175 g_object_set(G_OBJECT(element), "latency", 0, NULL);
7176 MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
7177 G_CALLBACK (__mmplayer_gst_wfd_dynamic_pad), player );
7179 player->use_decodebin = FALSE;
7184 case MM_PLAYER_URI_TYPE_URL_HTTP:
7186 gchar *user_agent, *proxy, *cookies, **cookie_list;
7187 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7188 user_agent = proxy = cookies = NULL;
7190 gint mode = MM_PLAYER_PD_MODE_NONE;
7192 mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
7194 player->pd_mode = mode;
7196 debug_log("http playback, PD mode : %d\n", player->pd_mode);
7198 if ( ! MMPLAYER_IS_HTTP_PD(player) )
7200 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
7203 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
7206 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
7209 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
7210 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
7211 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
7212 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7214 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7215 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7217 debug_log("get timeout from ini\n");
7218 http_timeout = player->ini.http_timeout;
7222 secure_debug_log("location : %s\n", player->profile.uri);
7223 secure_debug_log("cookies : %s\n", cookies);
7224 secure_debug_log("proxy : %s\n", proxy);
7225 secure_debug_log("user_agent : %s\n", user_agent);
7226 debug_log("timeout : %d\n", http_timeout);
7228 /* setting property to streaming source */
7229 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7230 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7231 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
7233 /* check if prosy is vailid or not */
7234 if ( util_check_valid_url ( proxy ) )
7235 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
7236 /* parsing cookies */
7237 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
7238 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
7240 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
7242 if ( MMPLAYER_URL_HAS_DASH_SUFFIX(player) )
7244 debug_warning("it's dash. and it's still experimental feature.");
7246 else if (MMPLAYER_URL_HAS_HLS_SUFFIX(player) )
7248 debug_warning("it's hls. using decodebin");
7251 else // progressive download
7253 gchar* location = NULL;
7255 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7259 mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
7261 MMPLAYER_FREEIF(player->pd_file_save_path);
7263 debug_log("PD Location : %s\n", path);
7267 player->pd_file_save_path = g_strdup(path);
7271 debug_error("can't find pd location so, it should be set \n");
7272 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
7276 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
7279 debug_error("failed to create PD push source element[%s].\n", "pdpushsrc");
7283 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
7284 g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
7286 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7288 g_object_get(element, "location", &location, NULL);
7289 debug_log("PD_LOCATION [%s].\n", location);
7297 case MM_PLAYER_URI_TYPE_FILE:
7300 #ifdef ENABLE_DRMSRC
7302 char* drmsrc = player->ini.name_of_drmsrc;
7304 debug_log("using [%s] for 'file://' handler.\n", drmsrc);
7306 element = gst_element_factory_make(drmsrc, "source");
7309 debug_error("failed to create %s\n", drmsrc);
7313 debug_log("using filesrc for 'file://' handler.\n");
7315 element = gst_element_factory_make("filesrc", "source");
7319 debug_error("failed to create filesrc\n");
7323 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
7324 //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
7328 case MM_PLAYER_URI_TYPE_SS:
7330 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
7331 element = gst_element_factory_make("souphttpsrc", "http streaming source");
7334 debug_error("failed to create http streaming source element[%s]", player->ini.name_of_httpsrc);
7338 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
7340 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
7341 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
7343 debug_log("get timeout from ini\n");
7344 http_timeout = player->ini.http_timeout;
7347 /* setting property to streaming source */
7348 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
7349 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
7354 case MM_PLAYER_URI_TYPE_BUFF:
7356 guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
7358 debug_log("mem src is selected\n");
7360 element = gst_element_factory_make("appsrc", "buff-source");
7363 debug_error("failed to create appsrc element\n");
7367 g_object_set( element, "stream-type", stream_type, NULL );
7368 //g_object_set( element, "size", player->mem_buf.len, NULL );
7369 //g_object_set( element, "blocksize", (guint64)20480, NULL );
7371 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7372 G_CALLBACK(__gst_appsrc_seek_data), player);
7373 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7374 G_CALLBACK(__gst_appsrc_feed_data), player);
7375 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
7376 G_CALLBACK(__gst_appsrc_enough_data), player);
7381 case MM_PLAYER_URI_TYPE_MEM:
7383 guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
7385 debug_log("mem src is selected\n");
7387 element = gst_element_factory_make("appsrc", "mem-source");
7390 debug_error("failed to create appsrc element\n");
7394 g_object_set( element, "stream-type", stream_type, NULL );
7395 g_object_set( element, "size", player->mem_buf.len, NULL );
7396 g_object_set( element, "blocksize", (guint64)20480, NULL );
7398 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
7399 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
7400 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
7401 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
7404 case MM_PLAYER_URI_TYPE_URL:
7407 case MM_PLAYER_URI_TYPE_TEMP:
7410 case MM_PLAYER_URI_TYPE_NONE:
7415 /* check source element is OK */
7418 debug_error("no source element was created.\n");
7422 /* take source element */
7423 mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
7424 mainbin[MMPLAYER_M_SRC].gst = element;
7425 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
7427 if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL))
7429 player->streamer = __mm_player_streaming_create();
7430 __mm_player_streaming_initialize(player->streamer);
7433 if ( MMPLAYER_IS_HTTP_PD(player) )
7435 gdouble pre_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
7437 debug_log ("Picked queue2 element(pre buffer : %d sec)....\n", pre_buffering_time);
7438 element = gst_element_factory_make("queue2", "queue2");
7441 debug_error ( "failed to create http streaming buffer element\n" );
7446 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
7447 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
7448 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
7450 pre_buffering_time = (pre_buffering_time > 0)?(pre_buffering_time):(player->ini.http_buffering_time);
7452 __mm_player_streaming_set_queue2(player->streamer,
7455 player->ini.http_max_size_bytes,
7458 player->ini.http_buffering_limit,
7464 /* create autoplugging element if src element is not a rtsp src */
7465 if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
7466 (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD))
7469 enum MainElementID elemId = MMPLAYER_M_NUM;
7471 if ((player->use_decodebin) &&
7472 ((MMPLAYER_IS_HTTP_PD(player)) ||
7473 (!MMPLAYER_IS_HTTP_STREAMING(player))))
7475 elemId = MMPLAYER_M_AUTOPLUG;
7476 element = __mmplayer_create_decodebin(player);
7477 need_state_holder = FALSE;
7481 elemId = MMPLAYER_M_TYPEFIND;
7482 element = gst_element_factory_make("typefind", "typefinder");
7483 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
7484 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
7488 /* check autoplug element is OK */
7491 debug_error("can not create element (%d)\n", elemId);
7495 mainbin[elemId].id = elemId;
7496 mainbin[elemId].gst = element;
7498 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
7501 /* add elements to pipeline */
7502 if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
7504 debug_error("Failed to add elements to pipeline\n");
7509 /* linking elements in the bucket by added order. */
7510 if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
7512 debug_error("Failed to link some elements\n");
7517 /* create fakesink element for keeping the pipeline state PAUSED. if needed */
7518 if ( need_state_holder )
7521 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
7522 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
7524 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7526 debug_error ("fakesink element could not be created\n");
7529 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_IS_SINK);
7531 /* take ownership of fakesink. we are reusing it */
7532 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
7535 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
7536 mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
7538 debug_error("failed to add fakesink to bin\n");
7543 /* now we have completed mainbin. take it */
7544 player->pipeline->mainbin = mainbin;
7546 /* connect bus callback */
7547 bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
7550 debug_error ("cannot get bus from pipeline.\n");
7554 player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
7556 player->context.thread_default = g_main_context_get_thread_default();
7558 if (NULL == player->context.thread_default)
7560 player->context.thread_default = g_main_context_default();
7561 debug_log("thread-default context is the global default context");
7563 debug_warning("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
7565 /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
7566 if ( __mmplayer_check_subtitle ( player ) )
7568 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
7569 debug_error("fail to create subtitle src\n");
7572 /* set sync handler to get tag synchronously */
7573 gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player);
7576 gst_object_unref(GST_OBJECT(bus));
7577 g_list_free(element_bucket);
7581 return MM_ERROR_NONE;
7585 __mmplayer_gst_destroy_pipeline(player);
7586 g_list_free(element_bucket);
7588 /* release element which are not added to bin */
7589 for ( i = 1; i < MMPLAYER_M_NUM; i++ ) /* NOTE : skip pipeline */
7591 if ( mainbin[i].gst )
7593 GstObject* parent = NULL;
7594 parent = gst_element_get_parent( mainbin[i].gst );
7598 gst_object_unref(GST_OBJECT(mainbin[i].gst));
7599 mainbin[i].gst = NULL;
7603 gst_object_unref(GST_OBJECT(parent));
7608 /* release pipeline with it's childs */
7609 if ( mainbin[MMPLAYER_M_PIPE].gst )
7611 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7614 MMPLAYER_FREEIF( player->pipeline );
7615 MMPLAYER_FREEIF( mainbin );
7617 return MM_ERROR_PLAYER_INTERNAL;
7620 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
7622 GSource *source = NULL;
7626 source = g_main_context_find_source_by_id (context, source_id);
7630 debug_warning("context: %p, source id: %d, source: %p", context, source_id, source);
7631 g_source_destroy(source);
7638 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
7641 int ret = MM_ERROR_NONE;
7645 return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
7647 /* cleanup stuffs */
7648 MMPLAYER_FREEIF(player->type);
7649 player->have_dynamic_pad = FALSE;
7650 player->no_more_pad = FALSE;
7651 player->num_dynamic_pad = 0;
7652 player->demux_pad_index = 0;
7653 player->subtitle_language_list = NULL;
7654 player->use_deinterleave = FALSE;
7655 player->pp_rebuilding = FALSE;
7656 player->max_audio_channels = 0;
7657 player->video_share_api_delta = 0;
7658 player->video_share_clock_delta = 0;
7659 player->video_hub_download_mode = 0;
7661 MMPLAYER_FREEIF(player->font_desc);
7662 player->font_color = 0;
7663 player->font_bg_color = 0;
7665 __mmplayer_post_proc_reset(player);
7667 if (player->streamer)
7669 __mm_player_streaming_deinitialize (player->streamer);
7670 __mm_player_streaming_destroy(player->streamer);
7671 player->streamer = NULL;
7674 /* cleanup unlinked mime type */
7675 MMPLAYER_FREEIF(player->unlinked_audio_mime);
7676 MMPLAYER_FREEIF(player->unlinked_video_mime);
7677 MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7679 /* cleanup running stuffs */
7680 __mmplayer_cancel_eos_timer( player );
7682 /* remove sound cb */
7683 if ( MM_ERROR_NONE != mm_sound_remove_active_device_changed_callback(MM_PLAYER_NAME))
7685 debug_error("failed to mm_sound_remove_active_device_changed_callback");
7688 /* cleanup gst stuffs */
7689 if ( player->pipeline )
7691 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7692 GstTagList* tag_list = player->pipeline->tag_list;
7694 /* first we need to disconnect all signal hander */
7695 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_ALL );
7697 /* disconnecting bus watch */
7698 if ( player->bus_watcher )
7699 __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7700 player->bus_watcher = 0;
7704 MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7705 MMPlayerGstElement* videobin = player->pipeline->videobin;
7706 MMPlayerGstElement* textbin = player->pipeline->textbin;
7707 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
7708 gst_bus_set_sync_handler (bus, NULL, NULL);
7709 gst_object_unref(bus);
7711 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7712 ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
7713 if ( ret != MM_ERROR_NONE )
7715 debug_error("fail to change state to NULL\n");
7716 return MM_ERROR_PLAYER_INTERNAL;
7719 debug_warning("succeeded in chaning state to NULL\n");
7721 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7724 if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
7725 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7727 /* free avsysaudiosink
7728 avsysaudiosink should be unref when destory pipeline just after start play with BT.
7729 Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7731 MMPLAYER_FREEIF( audiobin );
7732 MMPLAYER_FREEIF( videobin );
7733 MMPLAYER_FREEIF( textbin );
7734 MMPLAYER_FREEIF( mainbin );
7738 gst_tag_list_free(tag_list);
7740 MMPLAYER_FREEIF( player->pipeline );
7742 MMPLAYER_FREEIF(player->album_art);
7744 if (player->v_stream_caps)
7746 gst_caps_unref(player->v_stream_caps);
7747 player->v_stream_caps = NULL;
7750 if ( player->sink_elements )
7751 g_list_free ( player->sink_elements );
7752 player->sink_elements = NULL;
7754 debug_warning("finished destroy pipeline\n");
7761 static int __gst_realize(mm_player_t* player) // @
7764 int ret = MM_ERROR_NONE;
7768 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7770 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7772 ret = __mmplayer_gst_create_pipeline(player);
7775 debug_error("failed to create pipeline\n");
7779 /* set pipeline state to READY */
7780 /* NOTE : state change to READY must be performed sync. */
7781 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7782 ret = __mmplayer_gst_set_state(player,
7783 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7785 if ( ret != MM_ERROR_NONE )
7787 /* return error if failed to set state */
7788 debug_error("failed to set READY state");
7793 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
7796 /* create dot before error-return. for debugging */
7797 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
7804 static int __gst_unrealize(mm_player_t* player) // @
7806 int ret = MM_ERROR_NONE;
7810 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7812 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7813 MMPLAYER_PRINT_STATE(player);
7815 /* release miscellaneous information */
7816 __mmplayer_release_misc( player );
7818 /* destroy pipeline */
7819 ret = __mmplayer_gst_destroy_pipeline( player );
7820 if ( ret != MM_ERROR_NONE )
7822 debug_error("failed to destory pipeline\n");
7826 /* release miscellaneous information.
7827 these info needs to be released after pipeline is destroyed. */
7828 __mmplayer_release_misc_post( player );
7830 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
7837 static int __gst_pending_seek ( mm_player_t* player )
7839 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7840 int ret = MM_ERROR_NONE;
7844 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7846 if ( !player->pending_seek.is_pending )
7848 debug_log("pending seek is not reserved. nothing to do.\n" );
7852 /* check player state if player could pending seek or not. */
7853 current_state = MMPLAYER_CURRENT_STATE(player);
7855 if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING )
7857 debug_warning("try to pending seek in %s state, try next time. \n",
7858 MMPLAYER_STATE_GET_NAME(current_state));
7862 debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
7864 ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
7866 if ( MM_ERROR_NONE != ret )
7867 debug_error("failed to seek pending postion. just keep staying current position.\n");
7869 player->pending_seek.is_pending = FALSE;
7876 static int __gst_start(mm_player_t* player) // @
7878 gboolean sound_extraction = 0;
7879 int ret = MM_ERROR_NONE;
7883 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7885 /* get sound_extraction property */
7886 mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7888 /* NOTE : if SetPosition was called before Start. do it now */
7889 /* streaming doesn't support it. so it should be always sync */
7890 /* !! create one more api to check if there is pending seek rather than checking variables */
7891 if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
7893 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7894 ret = __gst_pause(player, FALSE);
7895 if ( ret != MM_ERROR_NONE )
7897 debug_error("failed to set state to PAUSED for pending seek\n");
7901 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7903 if ( sound_extraction )
7905 debug_log("setting pcm extraction\n");
7907 ret = __mmplayer_set_pcm_extraction(player);
7908 if ( MM_ERROR_NONE != ret )
7910 debug_warning("failed to set pcm extraction\n");
7916 if ( MM_ERROR_NONE != __gst_pending_seek(player) )
7918 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
7923 debug_log("current state before doing transition");
7924 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7925 MMPLAYER_PRINT_STATE(player);
7927 /* set pipeline state to PLAYING */
7928 ret = __mmplayer_gst_set_state(player,
7929 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
7930 if (ret == MM_ERROR_NONE)
7932 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7936 debug_error("failed to set state to PLAYING");
7940 /* generating debug info before returning error */
7941 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
7948 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
7952 return_if_fail(player
7954 && player->pipeline->audiobin
7955 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7957 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
7964 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
7968 return_if_fail(player
7970 && player->pipeline->audiobin
7971 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
7973 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
7978 static int __gst_stop(mm_player_t* player) // @
7980 GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7981 MMHandleType attrs = 0;
7982 gboolean fadedown = FALSE;
7983 gboolean rewind = FALSE;
7985 int ret = MM_ERROR_NONE;
7990 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7991 return_val_if_fail ( player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7993 debug_log("current state before doing transition");
7994 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7995 MMPLAYER_PRINT_STATE(player);
7997 attrs = MMPLAYER_GET_ATTRS(player);
8000 debug_error("cannot get content attribute\n");
8001 return MM_ERROR_PLAYER_INTERNAL;
8004 mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
8006 /* enable fadedown */
8007 if (fadedown || player->sm.by_asm_cb)
8008 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
8010 /* Just set state to PAUESED and the rewind. it's usual player behavior. */
8011 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
8013 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF ||
8014 player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
8016 state = GST_STATE_READY;
8020 state = GST_STATE_PAUSED;
8022 if ( ! MMPLAYER_IS_STREAMING(player) ||
8023 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked)) {
8029 ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, FALSE, timeout );
8031 /* disable fadeout */
8032 if (fadedown || player->sm.by_asm_cb)
8033 __mmplayer_undo_sound_fadedown(player);
8035 /* return if set_state has failed */
8036 if ( ret != MM_ERROR_NONE )
8038 debug_error("failed to set state.\n");
8045 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8046 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
8047 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
8049 debug_warning("failed to rewind\n");
8050 ret = MM_ERROR_PLAYER_SEEK;
8055 player->sent_bos = FALSE;
8057 /* wait for seek to complete */
8058 change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
8059 if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
8061 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
8065 debug_error("fail to stop player.\n");
8066 ret = MM_ERROR_PLAYER_INTERNAL;
8067 __mmplayer_dump_pipeline_state(player);
8070 /* generate dot file if enabled */
8071 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
8078 int __gst_pause(mm_player_t* player, gboolean async) // @
8080 int ret = MM_ERROR_NONE;
8084 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
8085 return_val_if_fail(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8087 debug_log("current state before doing transition");
8088 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
8089 MMPLAYER_PRINT_STATE(player);
8091 /* set pipeline status to PAUSED */
8092 player->ignore_asyncdone = TRUE;
8094 ret = __mmplayer_gst_set_state(player,
8095 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
8097 player->ignore_asyncdone = FALSE;
8099 if ( FALSE == async )
8101 if ( ret != MM_ERROR_NONE )
8103 GstMessage *msg = NULL;
8104 GTimer *timer = NULL;
8105 gdouble MAX_TIMEOUT_SEC = 3;
8107 debug_error("failed to set state to PAUSED");
8109 timer = g_timer_new();
8110 g_timer_start(timer);
8112 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
8113 gboolean got_msg = FALSE;
8114 /* check if gst error posted or not */
8117 msg = gst_bus_timed_pop(bus, GST_SECOND /2);
8120 if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
8122 GError *error = NULL;
8124 /* parse error code */
8125 gst_message_parse_error(msg, &error, NULL);
8127 if ( gst_structure_has_name ( msg->structure, "streaming_error" ) )
8129 /* Note : the streaming error from the streaming source is handled
8130 * using __mmplayer_handle_streaming_error.
8132 __mmplayer_handle_streaming_error ( player, msg );
8137 debug_error("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
8139 if (error->domain == GST_STREAM_ERROR)
8141 ret = __gst_handle_stream_error( player, error, msg );
8143 else if (error->domain == GST_RESOURCE_ERROR)
8145 ret = __gst_handle_resource_error( player, error->code );
8147 else if (error->domain == GST_LIBRARY_ERROR)
8149 ret = __gst_handle_library_error( player, error->code );
8151 else if (error->domain == GST_CORE_ERROR)
8153 ret = __gst_handle_core_error( player, error->code );
8158 player->msg_posted = TRUE;
8160 gst_message_unref(msg);
8162 } while (!got_msg && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
8164 gst_object_unref(bus);
8165 g_timer_stop (timer);
8166 g_timer_destroy (timer);
8170 else if ( (!player->pipeline->videobin) && (!player->pipeline->audiobin) )
8172 if (MMPLAYER_IS_RTSP_STREAMING(player))
8174 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
8176 else if ( ret== MM_ERROR_NONE)
8178 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
8182 /* generate dot file before returning error */
8183 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
8190 int __gst_resume(mm_player_t* player, gboolean async) // @
8192 int ret = MM_ERROR_NONE;
8197 return_val_if_fail(player && player->pipeline,
8198 MM_ERROR_PLAYER_NOT_INITIALIZED);
8200 debug_log("current state before doing transition");
8201 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
8202 MMPLAYER_PRINT_STATE(player);
8204 /* generate dot file before returning error */
8205 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8207 __mmplayer_set_antishock( player , FALSE );
8210 debug_log("do async state transition to PLAYING.\n");
8212 /* set pipeline state to PLAYING */
8213 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
8215 ret = __mmplayer_gst_set_state(player,
8216 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
8217 if (ret != MM_ERROR_NONE)
8219 debug_error("failed to set state to PLAYING\n");
8226 // MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
8227 debug_log("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
8228 ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
8232 /* generate dot file before returning error */
8233 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
8241 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
8243 GstFormat fmt = GST_FORMAT_TIME;
8244 unsigned long dur_msec = 0;
8245 gint64 dur_nsec = 0;
8246 gint64 pos_nsec = 0;
8247 gboolean ret = TRUE;
8248 gboolean accurated = FALSE;
8249 GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
8252 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
8253 return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
8255 if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
8256 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
8259 /* check duration */
8260 /* NOTE : duration cannot be zero except live streaming.
8261 * Since some element could have some timing problemn with quering duration, try again.
8263 if ( !player->duration )
8265 if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
8269 player->duration = dur_nsec;
8272 if ( player->duration )
8274 dur_msec = GST_TIME_AS_MSECONDS(player->duration);
8278 debug_error("could not get the duration. fail to seek.\n");
8282 debug_log("playback rate: %f\n", player->playback_rate);
8284 mm_attrs_get_int_by_name(player->attrs,"accurate_seek", &accurated);
8287 seek_flags |= GST_SEEK_FLAG_ACCURATE;
8291 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
8297 case MM_PLAYER_POS_FORMAT_TIME:
8299 /* check position is valid or not */
8300 if ( position > dur_msec )
8303 debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
8305 if (player->doing_seek)
8307 debug_log("not completed seek");
8308 return MM_ERROR_PLAYER_DOING_SEEK;
8311 if ( !internal_called)
8312 player->doing_seek = TRUE;
8314 pos_nsec = position * G_GINT64_CONSTANT(1000000);
8316 if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked))
8318 gint64 cur_time = 0;
8319 GstFormat format = GST_FORMAT_TIME;
8321 /* get current position */
8322 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &cur_time);
8325 GstEvent *event = gst_event_new_seek (1.0,
8327 (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
8328 GST_SEEK_TYPE_SET, cur_time,
8329 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
8331 __gst_send_event_to_sink(player, event);
8334 __gst_pause( player, FALSE );
8337 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8338 GST_FORMAT_TIME, seek_flags,
8339 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8342 debug_error("failed to set position. dur[%lu] pos[%lu] pos_msec[%llu]\n", dur_msec, position, pos_nsec);
8348 case MM_PLAYER_POS_FORMAT_PERCENT:
8350 debug_log("seeking to (%lu)%% \n", position);
8352 if (player->doing_seek)
8354 debug_log("not completed seek");
8355 return MM_ERROR_PLAYER_DOING_SEEK;
8358 if ( !internal_called)
8359 player->doing_seek = TRUE;
8361 /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
8362 pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
8363 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
8364 GST_FORMAT_TIME, seek_flags,
8365 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
8368 debug_error("failed to set position. dur[%lud] pos[%lud] pos_msec[%llud]\n", dur_msec, position, pos_nsec);
8379 /* NOTE : store last seeking point to overcome some bad operation
8380 * ( returning zero when getting current position ) of some elements
8382 player->last_position = pos_nsec;
8384 /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
8385 if ( player->playback_rate > 1.0 )
8386 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
8389 return MM_ERROR_NONE;
8392 player->pending_seek.is_pending = TRUE;
8393 player->pending_seek.format = format;
8394 player->pending_seek.pos = position;
8396 debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
8397 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
8399 return MM_ERROR_NONE;
8402 debug_error("invalid arguments, position : %ld dur : %ld format : %d \n", position, dur_msec, format);
8403 return MM_ERROR_INVALID_ARGUMENT;
8406 player->doing_seek = FALSE;
8407 return MM_ERROR_PLAYER_SEEK;
8410 #define TRICKPLAY_OFFSET GST_MSECOND
8413 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
8415 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
8416 GstFormat fmt = GST_FORMAT_TIME;
8417 signed long long pos_msec = 0;
8418 gboolean ret = TRUE;
8420 return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
8421 MM_ERROR_PLAYER_NOT_INITIALIZED );
8423 current_state = MMPLAYER_CURRENT_STATE(player);
8425 /* NOTE : query position except paused state to overcome some bad operation
8426 * please refer to below comments in details
8428 if ( current_state != MM_PLAYER_STATE_PAUSED )
8430 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
8433 /* NOTE : get last point to overcome some bad operation of some elements
8434 * ( returning zero when getting current position in paused state
8435 * and when failed to get postion during seeking
8437 if ( ( current_state == MM_PLAYER_STATE_PAUSED )
8439 //|| ( player->last_position != 0 && pos_msec == 0 ) )
8441 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
8443 if(player->playback_rate < 0.0)
8444 pos_msec = player->last_position - TRICKPLAY_OFFSET;
8446 pos_msec = player->last_position;
8449 pos_msec = player->last_position;
8451 player->last_position = pos_msec;
8453 debug_log("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
8458 if (player->duration > 0 && pos_msec > player->duration) {
8459 pos_msec = player->duration;
8462 if (player->sm.keep_last_pos) {
8463 debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
8464 pos_msec = player->last_position;
8467 player->last_position = pos_msec;
8472 case MM_PLAYER_POS_FORMAT_TIME:
8473 *position = GST_TIME_AS_MSECONDS(pos_msec);
8476 case MM_PLAYER_POS_FORMAT_PERCENT:
8481 dur = player->duration / GST_SECOND;
8484 debug_log ("duration is [%d], so returning position 0\n",dur);
8489 pos = pos_msec / GST_SECOND;
8490 *position = pos * 100 / dur;
8495 return MM_ERROR_PLAYER_INTERNAL;
8498 return MM_ERROR_NONE;
8502 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
8504 #define STREAMING_IS_FINISHED 0
8505 #define BUFFERING_MAX_PER 100
8507 GstQuery *query = NULL;
8509 return_val_if_fail( player &&
8511 player->pipeline->mainbin,
8512 MM_ERROR_PLAYER_NOT_INITIALIZED );
8514 return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
8516 if (!MMPLAYER_IS_HTTP_STREAMING ( player ))
8518 /* and rtsp is not ready yet. */
8519 debug_warning ( "it's only used for http streaming case.\n" );
8520 return MM_ERROR_NONE;
8528 case MM_PLAYER_POS_FORMAT_PERCENT :
8530 gint start_per = -1, stop_per = -1;
8531 gint64 buffered_total = 0;
8533 unsigned long position = 0;
8534 guint curr_size_bytes = 0;
8535 gint64 buffering_left = -1;
8536 gint buffered_sec = -1;
8538 gint64 content_duration = player->duration;
8539 guint64 content_size = player->http_content_size;
8541 if (content_duration > 0)
8543 if (!__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position))
8545 debug_log ("[Time] pos %d ms / dur %d sec / %lld bytes", position, (guint)(content_duration/GST_SECOND), content_size);
8546 start_per = 100 * (position*GST_MSECOND) / content_duration;
8548 /* buffered size info from multiqueue */
8549 if (player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)
8551 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst), "curr-size-bytes", &curr_size_bytes, NULL);
8552 debug_log ("[MQ] curr_size_bytes = %d", curr_size_bytes);
8554 buffered_total += curr_size_bytes;
8557 /* buffered size info from queue2 */
8558 if (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
8560 query = gst_query_new_buffering ( GST_FORMAT_BYTES );
8561 if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query))
8563 GstBufferingMode mode;
8564 gint byte_in_rate = 0, byte_out_rate = 0;
8565 gint64 start_byte = 0, stop_byte = 0;
8566 guint num_of_ranges = 0;
8569 num_of_ranges = gst_query_get_n_buffering_ranges(query);
8570 for ( idx=0 ; idx<num_of_ranges ; idx++ )
8572 gst_query_parse_nth_buffering_range (query, idx, &start_byte, &stop_byte);
8573 debug_log ("[Q2][range %d] %lld ~ %lld\n", idx, start_byte, stop_byte);
8575 buffered_total += (stop_byte - start_byte);
8578 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, &buffering_left);
8579 debug_log ("[Q2] in_rate %d, out_rate %d, left %lld\n", byte_in_rate, byte_out_rate, buffering_left);
8581 gst_query_unref (query);
8584 if (buffering_left == STREAMING_IS_FINISHED)
8586 stop_per = BUFFERING_MAX_PER;
8590 guint dur_sec = (guint)(content_duration/GST_SECOND);
8591 guint avg_byterate = (dur_sec>0)?((guint)(content_size/dur_sec)):(0);
8593 if (avg_byterate > 0)
8594 buffered_sec = (gint)(buffered_total/avg_byterate);
8595 else if (player->total_maximum_bitrate > 0)
8596 buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_maximum_bitrate);
8597 else if (player->total_bitrate > 0)
8598 buffered_sec = (gint)(GET_BIT_FROM_BYTE(buffered_total)/(gint64)player->total_bitrate);
8600 if ((buffered_sec >= 0) && (dur_sec > 0))
8601 stop_per = start_per + (100 * buffered_sec / dur_sec);
8604 debug_log ("[Buffered Total] %lld bytes, %d sec, per %d~%d\n", buffered_total, buffered_sec, start_per, stop_per);
8608 if (((buffered_total == 0) || (start_per < 0) || (stop_per < 0)) &&
8609 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst))
8611 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
8612 if ( gst_element_query ( player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query ) )
8615 gint64 range_start_per = -1, range_stop_per = -1;
8617 gst_query_parse_buffering_range ( query, &format, &range_start_per, &range_stop_per, NULL );
8619 debug_log ("[Q2] range start %" G_GINT64_FORMAT " ~ stop %" G_GINT64_FORMAT "\n", range_start_per , range_stop_per);
8621 if (range_start_per != -1)
8622 start_per = (gint)(100 * range_start_per / GST_FORMAT_PERCENT_MAX);
8624 if (range_stop_per != -1)
8625 stop_per = (gint)(100 * range_stop_per / GST_FORMAT_PERCENT_MAX);
8627 gst_query_unref (query);
8631 *start_pos = (start_per < 100)?(start_per):(100);
8636 *stop_pos = (stop_per < 100)?(stop_per):(100);
8642 case MM_PLAYER_POS_FORMAT_TIME :
8643 debug_warning ( "Time format is not supported yet.\n" );
8650 debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
8652 return MM_ERROR_NONE;
8656 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
8662 debug_warning("set_message_callback is called with invalid player handle\n");
8663 return MM_ERROR_PLAYER_NOT_INITIALIZED;
8666 player->msg_cb = callback;
8667 player->msg_cb_param = user_param;
8669 debug_log("msg_cb : 0x%x msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
8673 return MM_ERROR_NONE;
8676 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
8678 int ret = MM_ERROR_PLAYER_INVALID_URI;
8683 return_val_if_fail ( uri , FALSE);
8684 return_val_if_fail ( data , FALSE);
8685 return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
8687 memset(data, 0, sizeof(MMPlayerParseProfile));
8689 if ((path = strstr(uri, "file://")))
8691 int file_stat = MM_ERROR_NONE;
8693 file_stat = util_exist_file_path(path + 7);
8695 if (file_stat == MM_ERROR_NONE)
8697 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
8699 if ( util_is_sdp_file ( path ) )
8701 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8702 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8706 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8708 ret = MM_ERROR_NONE;
8710 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8712 data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8716 debug_warning("could access %s.\n", path);
8719 else if ((path = strstr(uri, "buff://")))
8721 data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
8722 ret = MM_ERROR_NONE;
8724 else if ((path = strstr(uri, "rtsp://")))
8727 if((path = strstr(uri, "/wfd1.0/"))) {
8728 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
8729 data->uri_type = MM_PLAYER_URI_TYPE_URL_WFD;
8730 ret = MM_ERROR_NONE;
8731 debug_log("uri is actually a wfd client path. giving it to wfdrtspsrc\n");
8734 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
8735 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8736 ret = MM_ERROR_NONE;
8740 else if ((path = strstr(uri, "http://")))
8743 strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
8744 #ifdef MM_SMOOTH_STREAMING
8745 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8746 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8748 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8752 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8754 ret = MM_ERROR_NONE;
8757 else if ((path = strstr(uri, "https://")))
8760 strncpy(data->uri, uri, MM_MAX_URL_LEN -1);
8761 #ifdef MM_SMOOTH_STREAMING
8762 if (g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".ism/manifest") ||
8763 g_str_has_suffix (g_ascii_strdown(uri, strlen(uri)), ".isml/manifest"))
8765 data->uri_type = MM_PLAYER_URI_TYPE_SS;
8768 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
8770 ret = MM_ERROR_NONE;
8773 else if ((path = strstr(uri, "rtspu://")))
8776 strncpy(data->uri, uri, MM_MAX_URL_LEN -1);
8777 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8778 ret = MM_ERROR_NONE;
8781 else if ((path = strstr(uri, "rtspr://")))
8783 strncpy(data->uri, path, MM_MAX_URL_LEN -1);
8784 char *separater =strstr(path, "*");
8788 char *urgent = separater + strlen("*");
8790 if ((urgent_len = strlen(urgent))) {
8791 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
8792 strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN -1);
8793 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8794 ret = MM_ERROR_NONE;
8798 else if ((path = strstr(uri, "mms://")))
8801 strncpy(data->uri, uri, MM_MAX_URL_LEN -1);
8802 data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
8803 ret = MM_ERROR_NONE;
8806 else if ((path = strstr(uri, "mem://")))
8809 #define MM_MAX_EXT_SIZE 100
8811 char *buffer = NULL;
8812 char *seperator = strchr(path, ',');
8813 char ext[MM_MAX_EXT_SIZE] = {0,}, size[MM_MAX_EXT_SIZE] = {0,};
8816 if ((buffer = strstr(path, "ext="))) {
8817 buffer += strlen("ext=");
8819 if (strlen(buffer)) {
8820 strncpy(ext, buffer, MM_MAX_EXT_SIZE -1);
8822 if ((seperator = strchr(ext, ','))
8823 || (seperator = strchr(ext, ' '))
8824 || (seperator = strchr(ext, '\0'))) {
8825 seperator[0] = '\0';
8830 if ((buffer = strstr(path, "size="))) {
8831 buffer += strlen("size=");
8833 if (strlen(buffer) > 0) {
8834 strncpy(size, buffer, MM_MAX_EXT_SIZE -1);
8836 if ((seperator = strchr(size, ','))
8837 || (seperator = strchr(size, ' '))
8838 || (seperator = strchr(size, '\0'))) {
8839 seperator[0] = '\0';
8842 mem_size = atoi(size);
8847 debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
8848 if ( mem_size && param)
8851 data->mem_size = mem_size;
8852 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
8853 ret = MM_ERROR_NONE;
8859 int file_stat = MM_ERROR_NONE;
8861 file_stat = util_exist_file_path(uri);
8863 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8864 if (file_stat == MM_ERROR_NONE)
8866 g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", uri);
8868 if ( util_is_sdp_file( (char*)uri ) )
8870 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8871 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8875 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8877 ret = MM_ERROR_NONE;
8879 else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED)
8881 data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8885 debug_error ("invalid uri, could not play..\n");
8886 data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8890 if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
8891 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8892 } else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION){
8893 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8896 /* dump parse result */
8897 secure_debug_warning("incomming uri : %s\n", uri);
8898 debug_log("uri_type : %d, play_mode : %d, mem : 0x%x, mem_size : %d, urgent : %s\n",
8899 data->uri_type, data->play_mode, (guint)data->mem, data->mem_size, data->urgent);
8906 gboolean _asm_postmsg(gpointer *data)
8908 mm_player_t* player = (mm_player_t*)data;
8909 MMMessageParamType msg = {0, };
8912 return_val_if_fail ( player, FALSE );
8913 debug_warning("get notified");
8915 if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
8916 (player->cmd == MMPLAYER_COMMAND_UNREALIZE))
8918 debug_warning("dispatched");
8923 msg.union_type = MM_MSG_UNION_CODE;
8924 msg.code = player->sm.event_src;
8926 #if 0 // should remove
8927 if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
8929 /* fill the message with state of player */
8930 msg.state.current = MMPLAYER_CURRENT_STATE(player);
8931 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
8932 player->resumable_cancel_id = 0;
8937 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
8938 player->resume_event_id = 0;
8941 debug_warning("dispatched");
8945 gboolean _asm_lazy_pause(gpointer *data)
8947 mm_player_t* player = (mm_player_t*)data;
8948 int ret = MM_ERROR_NONE;
8952 return_val_if_fail ( player, FALSE );
8954 if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
8956 debug_log ("Ready to proceed lazy pause\n");
8957 ret = _mmplayer_pause((MMHandleType)player);
8958 if(MM_ERROR_NONE != ret)
8960 debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
8965 debug_log ("Invalid state to proceed lazy pause\n");
8969 if (player->pipeline && player->pipeline->audiobin)
8970 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
8972 player->sm.by_asm_cb = FALSE; //should be reset here
8980 __mmplayer_can_do_interrupt(mm_player_t *player)
8982 if (!player || !player->pipeline || !player->attrs)
8984 debug_warning("not initialized");
8988 if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction))
8990 debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction);
8994 /* check if seeking */
8995 if (player->doing_seek)
8997 MMMessageParamType msg_param;
8998 memset (&msg_param, 0, sizeof(MMMessageParamType));
8999 msg_param.code = MM_ERROR_PLAYER_SEEK;
9000 player->doing_seek = FALSE;
9001 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9005 /* check other thread */
9006 if (player->cmd_lock)
9008 if (!g_mutex_trylock(player->cmd_lock))
9010 debug_warning("locked already, cmd state : %d", player->cmd);
9012 /* check application command */
9013 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)
9015 debug_warning("playing.. should wait cmd lock then, will be interrupted");
9016 g_mutex_lock(player->cmd_lock);
9019 debug_warning("nothing to do");
9024 debug_warning("can interrupt immediately");
9037 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
9039 mm_player_t* player = (mm_player_t*) cb_data;
9040 ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
9041 int result = MM_ERROR_NONE;
9042 gboolean lazy_pause = FALSE;
9044 debug_warning("get notified");
9046 if (!__mmplayer_can_do_interrupt(player))
9048 debug_warning("no need to interrupt, so leave");
9052 player->sm.cb_pending = TRUE;
9053 debug_warning("asm event src type : %d, command : 0x%x", event_src, command);
9055 player->sm.by_asm_cb = TRUE;
9056 player->sm.event_src = event_src;
9058 /* first, check event source */
9059 if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
9061 int stop_by_asm = 0;
9062 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
9066 else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
9068 /* can use video overlay simultaneously */
9069 /* video resource conflict */
9070 if(player->pipeline->videobin)
9072 if (player->ini.multiple_codec_supported)
9074 debug_log("video conflict but, can support multiple video");
9075 result = _mmplayer_pause((MMHandleType)player);
9076 cb_res = ASM_CB_RES_PAUSE;
9080 debug_log("video conflict, can't support multiple video");
9081 result = _mmplayer_unrealize((MMHandleType)player);
9082 cb_res = ASM_CB_RES_STOP;
9085 else if (player->pipeline->audiobin)
9087 debug_log("audio resource conflict");
9088 result = _mmplayer_pause((MMHandleType)player);
9089 if (result != MM_ERROR_NONE)
9091 debug_warning("fail to set pause by asm");
9093 cb_res = ASM_CB_RES_PAUSE;
9097 #if 0 // should remove
9098 else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
9100 debug_warning("Got msg from asm for resumable canceled.\n");
9101 player->sm.antishock = TRUE;
9102 player->sm.by_asm_cb = FALSE;
9104 player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9105 cb_res = ASM_CB_RES_IGNORE;
9109 /* then, check command */
9112 case ASM_COMMAND_PLAY:
9113 debug_warning ("Got unexpected asm command (%d)", command);
9116 case ASM_COMMAND_STOP: // notification case
9118 GstFormat format = GST_FORMAT_TIME;
9119 debug_warning("Got msg from asm to stop");
9121 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &player->last_position)) {
9122 debug_error("failed to get position");
9123 player->last_position = 0;
9126 debug_log ("pos_msec = %"GST_TIME_FORMAT"", GST_TIME_ARGS(player->last_position));
9128 result = _mmplayer_stop((MMHandleType)player);
9129 if (result != MM_ERROR_NONE)
9131 debug_warning("fail to set stop state by asm");
9132 cb_res = ASM_CB_RES_IGNORE;
9136 cb_res = ASM_CB_RES_STOP;
9138 player->sm.by_asm_cb = FALSE; // reset because no message any more from asm
9139 player->sm.keep_last_pos = TRUE;
9143 case ASM_COMMAND_PAUSE:
9145 debug_warning("Got msg from asm to Pause");
9146 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9147 event_src == ASM_EVENT_SOURCE_NOTIFY_START ||
9148 event_src == ASM_EVENT_SOURCE_ALARM_START)
9150 if(__mmplayer_ignore_current_external_display_mode(player) == MM_ERROR_NONE)
9151 debug_log("screen will not display to external display");
9153 if(event_src == ASM_EVENT_SOURCE_CALL_START ||
9154 event_src == ASM_EVENT_SOURCE_ALARM_START ||
9155 event_src == ASM_EVENT_SOURCE_MEDIA)
9157 if ( ! MMPLAYER_IS_RTSP_STREAMING(player) ) {
9158 //hold 0.7 second to excute "fadedown mute" effect
9159 debug_warning ("do fade down->pause->undo fade down");
9161 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
9163 result = _mmplayer_pause((MMHandleType)player);
9164 if (result != MM_ERROR_NONE)
9166 debug_warning("fail to set Pause state by asm");
9167 cb_res = ASM_CB_RES_IGNORE;
9170 __mmplayer_undo_sound_fadedown(player);
9172 /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
9173 _mmplayer_unrealize((MMHandleType)player);
9176 #ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
9177 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
9179 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
9181 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
9182 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
9184 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
9185 debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
9190 debug_warning ("pause immediately");
9191 result = _mmplayer_pause((MMHandleType)player);
9193 cb_res = ASM_CB_RES_PAUSE;
9197 case ASM_COMMAND_RESUME:
9199 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
9200 player->sm.antishock = TRUE;
9201 player->sm.by_asm_cb = FALSE;
9203 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
9204 player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
9205 cb_res = ASM_CB_RES_IGNORE;
9217 player->sm.by_asm_cb = FALSE;
9219 player->sm.cb_pending = FALSE;
9220 MMPLAYER_CMD_UNLOCK( player );
9223 debug_warning("dispatched");
9228 _mmplayer_create_player(MMHandleType handle) // @
9230 mm_player_t* player = MM_PLAYER_CAST(handle);
9234 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9236 /* initialize player state */
9237 MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
9238 MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
9239 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
9240 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
9242 /* check current state */
9243 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
9245 /* construct attributes */
9246 player->attrs = _mmplayer_construct_attribute(handle);
9248 if ( !player->attrs )
9250 debug_error("Failed to construct attributes\n");
9254 /* initialize gstreamer with configured parameter */
9255 if ( ! __mmplayer_init_gstreamer(player) )
9257 debug_error("Initializing gstreamer failed\n");
9261 /* initialize factories if not using decodebin */
9262 if( player->factories == NULL )
9263 __mmplayer_init_factories(player);
9265 /* create lock. note that g_tread_init() has already called in gst_init() */
9266 player->fsink_lock = g_mutex_new();
9267 if ( ! player->fsink_lock )
9269 debug_error("Cannot create mutex for command lock\n");
9273 /* create repeat mutex */
9274 player->repeat_thread_mutex = g_mutex_new();
9275 if ( ! player->repeat_thread_mutex )
9277 debug_error("Cannot create repeat mutex\n");
9281 /* create repeat cond */
9282 player->repeat_thread_cond = g_cond_new();
9283 if ( ! player->repeat_thread_cond )
9285 debug_error("Cannot create repeat cond\n");
9289 /* create repeat thread */
9290 player->repeat_thread =
9291 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
9292 if ( ! player->repeat_thread )
9294 debug_error("failed to create repeat thread");
9298 /* create next play mutex */
9299 player->next_play_thread_mutex = g_mutex_new();
9300 if ( ! player->next_play_thread_mutex )
9302 debug_error("Cannot create next_play mutex\n");
9306 /* create next play cond */
9307 player->next_play_thread_cond = g_cond_new();
9308 if ( ! player->next_play_thread_cond )
9310 debug_error("Cannot create next_play cond\n");
9314 /* create next play thread */
9315 player->next_play_thread =
9316 g_thread_create (__mmplayer_next_play_thread, (gpointer)player, TRUE, NULL);
9317 if ( ! player->next_play_thread )
9319 debug_error("failed to create next play thread");
9323 if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
9325 debug_error("failed to initialize video capture\n");
9329 /* register to asm */
9330 if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
9332 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
9333 debug_error("failed to register asm server\n");
9334 return MM_ERROR_POLICY_INTERNAL;
9337 /* to add active device callback */
9338 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))
9340 debug_error("failed mm_sound_add_device_information_changed_callback \n");
9343 if (MMPLAYER_IS_HTTP_PD(player))
9345 player->pd_downloader = NULL;
9346 player->pd_file_save_path = NULL;
9349 player->streaming_type = STREAMING_SERVICE_NONE;
9351 /* give default value of audio effect setting */
9352 player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
9353 player->playback_rate = DEFAULT_PLAYBACK_RATE;
9355 player->play_subtitle = FALSE;
9356 player->use_textoverlay = FALSE;
9357 player->play_count = 0;
9358 player->use_decodebin = TRUE;
9359 player->ignore_asyncdone = FALSE;
9360 player->use_deinterleave = FALSE;
9361 player->pp_rebuilding = FALSE;
9362 player->max_audio_channels = 0;
9363 player->video_share_api_delta = 0;
9364 player->video_share_clock_delta = 0;
9365 player->has_closed_caption = FALSE;
9367 __mmplayer_post_proc_reset(player);
9369 if (player->ini.dump_element_keyword[0][0] == '\0')
9371 player->ini.set_dump_element_flag= FALSE;
9375 player->ini.set_dump_element_flag = TRUE;
9378 /* set player state to null */
9379 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9380 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
9382 return MM_ERROR_NONE;
9386 if ( player->fsink_lock )
9387 g_mutex_free( player->fsink_lock );
9388 player->fsink_lock = NULL;
9391 if ( player->repeat_thread_cond &&
9392 player->repeat_thread_mutex &&
9393 player->repeat_thread )
9395 player->repeat_thread_exit = TRUE;
9396 g_cond_signal( player->repeat_thread_cond );
9398 g_thread_join( player->repeat_thread );
9399 player->repeat_thread = NULL;
9401 g_mutex_free ( player->repeat_thread_mutex );
9402 player->repeat_thread_mutex = NULL;
9404 g_cond_free ( player->repeat_thread_cond );
9405 player->repeat_thread_cond = NULL;
9407 /* clear repeat thread mutex/cond if still alive
9408 * this can happen if only thread creating has failed
9410 if ( player->repeat_thread_mutex )
9411 g_mutex_free ( player->repeat_thread_mutex );
9413 if ( player->repeat_thread_cond )
9414 g_cond_free ( player->repeat_thread_cond );
9416 /* free next play thread */
9417 if ( player->next_play_thread_cond &&
9418 player->next_play_thread_mutex &&
9419 player->next_play_thread )
9421 player->next_play_thread_exit = TRUE;
9422 g_cond_signal( player->next_play_thread_cond );
9424 g_thread_join( player->next_play_thread );
9425 player->next_play_thread = NULL;
9427 g_mutex_free ( player->next_play_thread_mutex );
9428 player->next_play_thread_mutex = NULL;
9430 g_cond_free ( player->next_play_thread_cond );
9431 player->next_play_thread_cond = NULL;
9433 /* clear next play thread mutex/cond if still alive
9434 * this can happen if only thread creating has failed
9436 if ( player->next_play_thread_mutex )
9437 g_mutex_free ( player->next_play_thread_mutex );
9439 if ( player->next_play_thread_cond )
9440 g_cond_free ( player->next_play_thread_cond );
9442 /* release attributes */
9443 _mmplayer_deconstruct_attribute(handle);
9447 return MM_ERROR_PLAYER_INTERNAL;
9451 __mmplayer_init_gstreamer(mm_player_t* player) // @
9453 static gboolean initialized = FALSE;
9454 static const int max_argc = 50;
9456 gchar** argv = NULL;
9457 gchar** argv2 = NULL;
9464 debug_log("gstreamer already initialized.\n");
9469 argc = malloc( sizeof(int) );
9470 argv = malloc( sizeof(gchar*) * max_argc );
9471 argv2 = malloc( sizeof(gchar*) * max_argc );
9473 if ( !argc || !argv || !argv2)
9476 memset( argv, 0, sizeof(gchar*) * max_argc );
9477 memset( argv2, 0, sizeof(gchar*) * max_argc );
9481 argv[0] = g_strdup( "mmplayer" );
9484 for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
9486 if ( strlen( player->ini.gst_param[i] ) > 0 )
9488 argv[*argc] = g_strdup( player->ini.gst_param[i] );
9493 /* we would not do fork for scanning plugins */
9494 argv[*argc] = g_strdup("--gst-disable-registry-fork");
9497 /* check disable registry scan */
9498 if ( player->ini.skip_rescan )
9500 argv[*argc] = g_strdup("--gst-disable-registry-update");
9504 /* check disable segtrap */
9505 if ( player->ini.disable_segtrap )
9507 argv[*argc] = g_strdup("--gst-disable-segtrap");
9511 debug_log("initializing gstreamer with following parameter\n");
9512 debug_log("argc : %d\n", *argc);
9515 for ( i = 0; i < arg_count; i++ )
9518 debug_log("argv[%d] : %s\n", i, argv2[i]);
9522 /* initializing gstreamer */
9523 if ( ! gst_init_check (argc, &argv, &err))
9525 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
9534 for ( i = 0; i < arg_count; i++ )
9536 //debug_log("release - argv[%d] : %s\n", i, argv2[i]);
9537 MMPLAYER_FREEIF( argv2[i] );
9540 MMPLAYER_FREEIF( argv );
9541 MMPLAYER_FREEIF( argv2 );
9542 MMPLAYER_FREEIF( argc );
9552 for ( i = 0; i < arg_count; i++ )
9554 debug_log("free[%d] : %s\n", i, argv2[i]);
9555 MMPLAYER_FREEIF( argv2[i] );
9558 MMPLAYER_FREEIF( argv );
9559 MMPLAYER_FREEIF( argv2 );
9560 MMPLAYER_FREEIF( argc );
9566 __mmplayer_destroy_streaming_ext(mm_player_t* player)
9568 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9570 if (player->pd_downloader)
9572 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
9573 MMPLAYER_FREEIF(player->pd_downloader);
9576 if (MMPLAYER_IS_HTTP_PD(player))
9578 _mmplayer_destroy_pd_downloader((MMHandleType)player);
9579 MMPLAYER_FREEIF(player->pd_file_save_path);
9582 return MM_ERROR_NONE;
9586 _mmplayer_destroy(MMHandleType handle) // @
9588 mm_player_t* player = MM_PLAYER_CAST(handle);
9592 /* check player handle */
9593 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9595 /* destroy can called at anytime */
9596 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
9598 __mmplayer_destroy_streaming_ext(player);
9600 /* release repeat thread */
9601 if ( player->repeat_thread_cond &&
9602 player->repeat_thread_mutex &&
9603 player->repeat_thread )
9605 player->repeat_thread_exit = TRUE;
9606 g_cond_signal( player->repeat_thread_cond );
9608 debug_log("waitting for repeat thread exit\n");
9609 g_thread_join ( player->repeat_thread );
9610 g_mutex_free ( player->repeat_thread_mutex );
9611 g_cond_free ( player->repeat_thread_cond );
9612 debug_log("repeat thread released\n");
9615 /* release next play thread */
9616 if ( player->next_play_thread_cond &&
9617 player->next_play_thread_mutex &&
9618 player->next_play_thread )
9620 player->next_play_thread_exit = TRUE;
9621 g_cond_signal( player->next_play_thread_cond );
9623 debug_log("waitting for next play thread exit\n");
9624 g_thread_join ( player->next_play_thread );
9625 g_mutex_free ( player->next_play_thread_mutex );
9626 g_cond_free ( player->next_play_thread_cond );
9627 debug_log("next play thread released\n");
9630 _mmplayer_release_video_capture(player);
9632 /* flush any pending asm_cb */
9633 if (player->sm.cb_pending)
9635 /* set a flag for make sure asm_cb to be returned immediately */
9636 debug_warning("asm cb has pending state");
9637 player->sm.exit_cb = TRUE;
9639 /* make sure to release any pending asm_cb which locked by cmd_lock */
9640 MMPLAYER_CMD_UNLOCK(player);
9642 MMPLAYER_CMD_LOCK(player);
9646 if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
9648 debug_error("failed to deregister asm server\n");
9651 #ifdef USE_LAZY_PAUSE
9652 if (player->lazy_pause_event_id)
9654 __mmplayer_remove_g_source_from_context(player->context.global_default, player->lazy_pause_event_id);
9655 player->lazy_pause_event_id = 0;
9659 if (player->resume_event_id)
9661 g_source_remove (player->resume_event_id);
9662 player->resume_event_id = 0;
9665 if (player->resumable_cancel_id)
9667 g_source_remove (player->resumable_cancel_id);
9668 player->resumable_cancel_id = 0;
9671 /* release pipeline */
9672 if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
9674 debug_error("failed to destory pipeline\n");
9675 return MM_ERROR_PLAYER_INTERNAL;
9678 if (player->is_external_subtitle_present && player->subtitle_language_list)
9680 g_list_free (player->subtitle_language_list);
9681 player->subtitle_language_list = NULL;
9684 __mmplayer_release_dump_list (player->dump_list);
9686 /* release miscellaneous information.
9687 these info needs to be released after pipeline is destroyed. */
9688 __mmplayer_release_misc_post( player );
9690 /* release attributes */
9691 _mmplayer_deconstruct_attribute( handle );
9693 /* release factories */
9694 __mmplayer_release_factories( player );
9697 if ( player->fsink_lock )
9698 g_mutex_free( player->fsink_lock );
9700 if ( player->msg_cb_lock )
9701 g_mutex_free( player->msg_cb_lock );
9705 return MM_ERROR_NONE;
9709 __mmplayer_realize_streaming_ext(mm_player_t* player)
9711 int ret = MM_ERROR_NONE;
9714 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9716 if (MMPLAYER_IS_HTTP_PD(player))
9718 gboolean bret = FALSE;
9720 player->pd_downloader = _mmplayer_create_pd_downloader();
9721 if ( !player->pd_downloader )
9723 debug_error ("Unable to create PD Downloader...");
9724 ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
9727 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
9731 debug_error ("Unable to create PD Downloader...");
9732 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
9741 _mmplayer_realize(MMHandleType hplayer) // @
9743 mm_player_t* player = (mm_player_t*)hplayer;
9746 int application_pid = -1;
9747 gboolean update_registry = FALSE;
9748 MMHandleType attrs = 0;
9749 int ret = MM_ERROR_NONE;
9753 /* check player handle */
9754 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9756 /* check current state */
9757 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
9759 attrs = MMPLAYER_GET_ATTRS(player);
9762 debug_error("fail to get attributes.\n");
9763 return MM_ERROR_PLAYER_INTERNAL;
9766 mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
9767 player->sm.pid = application_pid;
9769 mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
9770 mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m);
9772 ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
9774 if (ret != MM_ERROR_NONE)
9776 debug_error("failed to parse profile\n");
9780 /* FIXIT : we can use thouse in player->profile directly */
9781 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
9783 player->mem_buf.buf = (char *)player->profile.mem;
9784 player->mem_buf.len = player->profile.mem_size;
9785 player->mem_buf.offset = 0;
9788 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
9790 debug_warning("mms protocol is not supported format.\n");
9791 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9794 if (MMPLAYER_IS_STREAMING(player))
9795 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
9797 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
9799 player->needed_v_parser = FALSE;
9800 player->smooth_streaming = FALSE;
9801 player->videodec_linked = 0;
9802 player->videosink_linked = 0;
9803 player->audiodec_linked = 0;
9804 player->audiosink_linked = 0;
9805 player->textsink_linked = 0;
9806 player->is_external_subtitle_present = FALSE;
9807 /* set the subtitle ON default */
9808 player->is_subtitle_off = FALSE;
9810 /* registry should be updated for downloadable codec */
9811 mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
9813 if ( update_registry )
9815 debug_log("updating registry...\n");
9816 gst_update_registry();
9818 /* then we have to rebuild factories */
9819 __mmplayer_release_factories( player );
9820 __mmplayer_init_factories(player);
9823 /* realize pipeline */
9824 ret = __gst_realize( player );
9825 if ( ret != MM_ERROR_NONE )
9827 debug_error("fail to realize the player.\n");
9831 ret = __mmplayer_realize_streaming_ext(player);
9840 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
9843 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9845 /* destroy can called at anytime */
9846 if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
9848 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
9849 MMPLAYER_FREEIF(player->pd_downloader);
9853 return MM_ERROR_NONE;
9857 _mmplayer_unrealize(MMHandleType hplayer)
9859 mm_player_t* player = (mm_player_t*)hplayer;
9860 int ret = MM_ERROR_NONE;
9864 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
9866 /* check current state */
9867 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
9869 __mmplayer_unrealize_streaming_ext(player);
9871 /* unrealize pipeline */
9872 ret = __gst_unrealize( player );
9874 /* set asm stop if success */
9875 if (MM_ERROR_NONE == ret)
9877 if (player->sm.state != ASM_STATE_STOP)
9879 /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */
9880 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP, FALSE);
9883 debug_error("failed to set asm state to STOP");
9890 debug_error("failed and don't change asm state to stop");
9899 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
9901 mm_player_t* player = (mm_player_t*)hplayer;
9903 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9905 return __gst_set_message_callback(player, callback, user_param);
9909 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
9911 mm_player_t *player = (mm_player_t*)hplayer;
9913 return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
9915 *state = MMPLAYER_CURRENT_STATE(player);
9917 return MM_ERROR_NONE;
9922 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
9924 mm_player_t* player = (mm_player_t*) hplayer;
9925 GstElement* vol_element = NULL;
9930 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9932 debug_log("volume [L]=%f:[R]=%f\n",
9933 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
9935 /* invalid factor range or not */
9936 for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
9938 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
9939 debug_error("Invalid factor! (valid factor:0~1.0)\n");
9940 return MM_ERROR_INVALID_ARGUMENT;
9944 /* not support to set other value into each channel */
9945 if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
9946 return MM_ERROR_INVALID_ARGUMENT;
9948 /* Save volume to handle. Currently the first array element will be saved. */
9949 player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
9951 /* check pipeline handle */
9952 if ( ! player->pipeline || ! player->pipeline->audiobin )
9954 debug_log("audiobin is not created yet\n");
9955 debug_log("but, current stored volume will be set when it's created.\n");
9957 /* NOTE : stored volume will be used in create_audiobin
9958 * returning MM_ERROR_NONE here makes application to able to
9959 * set volume at anytime.
9961 return MM_ERROR_NONE;
9964 /* setting volume to volume element */
9965 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
9969 debug_log("volume is set [%f]\n", player->sound.volume);
9970 g_object_set(vol_element, "volume", player->sound.volume, NULL);
9975 return MM_ERROR_NONE;
9980 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
9982 mm_player_t* player = (mm_player_t*) hplayer;
9987 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9988 return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
9990 /* returning stored volume */
9991 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
9992 volume->level[i] = player->sound.volume;
9996 return MM_ERROR_NONE;
10002 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
10004 mm_player_t* player = (mm_player_t*) hplayer;
10005 GstElement* vol_element = NULL;
10009 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10011 /* mute value shoud 0 or 1 */
10012 if ( mute != 0 && mute != 1 )
10014 debug_error("bad mute value\n");
10016 /* FIXIT : definitly, we need _BAD_PARAM error code */
10017 return MM_ERROR_INVALID_ARGUMENT;
10020 player->sound.mute = mute;
10022 /* just hold mute value if pipeline is not ready */
10023 if ( !player->pipeline || !player->pipeline->audiobin )
10025 debug_log("pipeline is not ready. holding mute value\n");
10026 return MM_ERROR_NONE;
10029 vol_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
10031 /* NOTE : volume will only created when the bt is enabled */
10034 debug_log("mute : %d\n", mute);
10035 g_object_set(vol_element, "mute", mute, NULL);
10039 debug_log("volume elemnet is not created. using volume in audiosink\n");
10044 return MM_ERROR_NONE;
10048 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
10050 mm_player_t* player = (mm_player_t*) hplayer;
10054 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10055 return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
10057 /* just hold mute value if pipeline is not ready */
10058 if ( !player->pipeline || !player->pipeline->audiobin )
10060 debug_log("pipeline is not ready. returning stored value\n");
10061 *pmute = player->sound.mute;
10062 return MM_ERROR_NONE;
10065 *pmute = player->sound.mute;
10069 return MM_ERROR_NONE;
10073 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
10075 mm_player_t* player = (mm_player_t*) hplayer;
10079 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10081 player->video_stream_cb = callback;
10082 player->video_stream_cb_user_param = user_param;
10083 player->use_video_stream = TRUE;
10084 debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
10088 return MM_ERROR_NONE;
10092 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
10094 mm_player_t* player = (mm_player_t*) hplayer;
10098 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10100 player->audio_stream_cb = callback;
10101 player->audio_stream_cb_user_param = user_param;
10102 debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
10106 return MM_ERROR_NONE;
10110 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
10112 mm_player_t* player = (mm_player_t*) hplayer;
10116 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10117 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
10119 player->need_data_cb = callback;
10120 player->buffer_cb_user_param = user_param;
10122 debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
10126 return MM_ERROR_NONE;
10130 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
10132 mm_player_t* player = (mm_player_t*) hplayer;
10136 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10137 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
10139 player->enough_data_cb = callback;
10140 player->buffer_cb_user_param = user_param;
10142 debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
10146 return MM_ERROR_NONE;
10150 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
10152 mm_player_t* player = (mm_player_t*) hplayer;
10156 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10157 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
10159 player->seek_data_cb = callback;
10160 player->buffer_cb_user_param = user_param;
10162 debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
10166 return MM_ERROR_NONE;
10170 __mmplayer_start_streaming_ext(mm_player_t *player)
10172 gint ret = MM_ERROR_NONE;
10175 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10177 if (MMPLAYER_IS_HTTP_PD(player))
10179 if ( !player->pd_downloader )
10181 ret = __mmplayer_realize_streaming_ext(player);
10183 if ( ret != MM_ERROR_NONE)
10185 debug_error ("failed to realize streaming ext\n");
10190 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
10192 ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
10195 debug_error ("ERROR while starting PD...\n");
10196 return MM_ERROR_PLAYER_NOT_INITIALIZED;
10198 ret = MM_ERROR_NONE;
10207 _mmplayer_start(MMHandleType hplayer) // @
10209 mm_player_t* player = (mm_player_t*) hplayer;
10210 gint ret = MM_ERROR_NONE;
10214 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10216 /* check current state */
10217 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
10219 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10220 if ( ret != MM_ERROR_NONE )
10222 debug_error("failed to set asm state to PLAYING\n");
10226 /* NOTE : we should check and create pipeline again if not created as we destroy
10227 * whole pipeline when stopping in streamming playback
10229 if ( ! player->pipeline )
10231 ret = __gst_realize( player );
10232 if ( MM_ERROR_NONE != ret )
10234 debug_error("failed to realize before starting. only in streamming\n");
10240 ret = __mmplayer_start_streaming_ext(player);
10241 if ( ret != MM_ERROR_NONE )
10243 debug_error("failed to start streaming ext \n");
10246 /* start pipeline */
10247 ret = __gst_start( player );
10248 if ( ret != MM_ERROR_NONE )
10250 debug_error("failed to start player.\n");
10258 /* NOTE: post "not supported codec message" to application
10259 * when one codec is not found during AUTOPLUGGING in MSL.
10260 * So, it's separated with error of __mmplayer_gst_callback().
10261 * And, if any codec is not found, don't send message here.
10262 * Because GST_ERROR_MESSAGE is posted by other plugin internally.
10265 __mmplayer_handle_missed_plugin(mm_player_t* player)
10267 MMMessageParamType msg_param;
10268 memset (&msg_param, 0, sizeof(MMMessageParamType));
10269 gboolean post_msg_direct = FALSE;
10273 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10275 debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
10276 player->not_supported_codec, player->can_support_codec);
10278 if( player->not_found_demuxer )
10280 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10281 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
10283 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10284 MMPLAYER_FREEIF(msg_param.data);
10286 return MM_ERROR_NONE;
10289 if (player->not_supported_codec)
10291 if ( player->can_support_codec ) // There is one codec to play
10293 post_msg_direct = TRUE;
10297 if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
10298 post_msg_direct = TRUE;
10301 if ( post_msg_direct )
10303 MMMessageParamType msg_param;
10304 memset (&msg_param, 0, sizeof(MMMessageParamType));
10306 if ( player->not_supported_codec == MISSING_PLUGIN_AUDIO )
10308 debug_warning("not found AUDIO codec, posting error code to application.\n");
10310 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10311 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10313 else if ( player->not_supported_codec == MISSING_PLUGIN_VIDEO )
10315 debug_warning("not found VIDEO codec, posting error code to application.\n");
10317 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
10318 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
10321 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10323 MMPLAYER_FREEIF(msg_param.data);
10325 return MM_ERROR_NONE;
10327 else // no any supported codec case
10329 debug_warning("not found any codec, posting error code to application.\n");
10331 if ( player->not_supported_codec == MISSING_PLUGIN_AUDIO )
10333 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
10334 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
10338 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
10339 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
10342 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10344 MMPLAYER_FREEIF(msg_param.data);
10350 return MM_ERROR_NONE;
10353 static void __mmplayer_check_pipeline(mm_player_t* player)
10355 GstState element_state = GST_STATE_VOID_PENDING;
10356 GstState element_pending_state = GST_STATE_VOID_PENDING;
10358 int ret = MM_ERROR_NONE;
10360 if (player->pp_rebuilding)
10362 debug_warning("pipeline is under construction.\n");
10364 MMPLAYER_PLAYBACK_LOCK(player);
10365 MMPLAYER_PLAYBACK_UNLOCK(player);
10367 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
10369 /* wait for state transition */
10370 ret = gst_element_get_state( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND );
10372 if ( ret == GST_STATE_CHANGE_FAILURE )
10374 debug_error("failed to change pipeline state within %d sec\n", timeout );
10379 /* NOTE : it should be able to call 'stop' anytime*/
10381 _mmplayer_stop(MMHandleType hplayer) // @
10383 mm_player_t* player = (mm_player_t*)hplayer;
10384 int ret = MM_ERROR_NONE;
10388 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10390 /* check current state */
10391 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
10393 /* check pipline building state */
10394 __mmplayer_check_pipeline(player);
10396 /* NOTE : application should not wait for EOS after calling STOP */
10397 __mmplayer_cancel_eos_timer( player );
10399 __mmplayer_unrealize_streaming_ext(player);
10402 player->doing_seek = FALSE;
10404 /* stop pipeline */
10405 ret = __gst_stop( player );
10407 if ( ret != MM_ERROR_NONE )
10409 debug_error("failed to stop player.\n");
10418 _mmplayer_pause(MMHandleType hplayer) // @
10420 mm_player_t* player = (mm_player_t*)hplayer;
10421 GstFormat fmt = GST_FORMAT_TIME;
10422 gint64 pos_msec = 0;
10423 gboolean async = FALSE;
10424 gint ret = MM_ERROR_NONE;
10428 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10430 /* check current state */
10431 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
10433 /* check pipline building state */
10434 __mmplayer_check_pipeline(player);
10436 switch (MMPLAYER_CURRENT_STATE(player))
10438 case MM_PLAYER_STATE_READY:
10440 /* check prepare async or not.
10441 * In the case of streaming playback, it's recommned to avoid blocking wait.
10443 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10444 debug_log("prepare working mode : %s", (async ? "async" : "sync"));
10448 case MM_PLAYER_STATE_PLAYING:
10450 /* NOTE : store current point to overcome some bad operation
10451 * ( returning zero when getting current position in paused state) of some
10454 if ( !gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec))
10455 debug_warning("getting current position failed in paused\n");
10457 player->last_position = pos_msec;
10462 /* pause pipeline */
10463 ret = __gst_pause( player, async );
10465 if ( ret != MM_ERROR_NONE )
10467 debug_error("failed to pause player. ret : 0x%x\n", ret);
10476 _mmplayer_resume(MMHandleType hplayer)
10478 mm_player_t* player = (mm_player_t*)hplayer;
10479 int ret = MM_ERROR_NONE;
10480 gboolean async = FALSE;
10484 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10486 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
10489 debug_error("failed to set asm state to PLAYING\n");
10493 /* check current state */
10494 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
10496 /* resume pipeline */
10497 ret = __gst_resume( player, async );
10499 if ( ret != MM_ERROR_NONE )
10501 debug_error("failed to resume player.\n");
10510 __mmplayer_set_play_count(mm_player_t* player, gint count)
10512 MMHandleType attrs = 0;
10516 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10518 attrs = MMPLAYER_GET_ATTRS(player);
10521 debug_error("fail to get attributes.\n");
10522 return MM_ERROR_PLAYER_INTERNAL;
10525 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10526 if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
10527 debug_error("failed to commit\n");
10531 return MM_ERROR_NONE;
10535 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
10537 mm_player_t* player = (mm_player_t*)hplayer;
10538 gint64 start_pos = 0;
10539 gint64 end_pos = 0;
10540 gint infinity = -1;
10544 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10545 return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
10547 player->section_repeat = TRUE;
10548 player->section_repeat_start = start;
10549 player->section_repeat_end = end;
10551 start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
10552 end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
10554 __mmplayer_set_play_count( player, infinity );
10556 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10557 player->playback_rate,
10559 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10560 GST_SEEK_TYPE_SET, start_pos,
10561 GST_SEEK_TYPE_SET, end_pos)))
10563 debug_error("failed to activate section repeat\n");
10565 return MM_ERROR_PLAYER_SEEK;
10568 debug_log("succeeded to set section repeat from %d to %d\n",
10569 player->section_repeat_start, player->section_repeat_end);
10573 return MM_ERROR_NONE;
10577 __mmplayer_set_pcm_extraction(mm_player_t* player)
10579 gint64 start_nsec = 0;
10580 gint64 end_nsec = 0;
10581 gint64 dur_nsec = 0;
10582 gint64 dur_msec = 0;
10583 GstFormat fmt = GST_FORMAT_TIME;
10584 int required_start = 0;
10585 int required_end = 0;
10590 return_val_if_fail( player, FALSE );
10592 mm_attrs_multiple_get(player->attrs,
10594 "pcm_extraction_start_msec", &required_start,
10595 "pcm_extraction_end_msec", &required_end,
10598 debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
10600 if (required_start == 0 && required_end == 0)
10602 debug_log("extracting entire stream");
10603 return MM_ERROR_NONE;
10605 else if (required_start < 0 || required_start > required_end || required_end < 0 )
10607 debug_log("invalid range for pcm extraction");
10608 return MM_ERROR_INVALID_ARGUMENT;
10612 ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
10615 debug_error("failed to get duration");
10616 return MM_ERROR_PLAYER_INTERNAL;
10618 dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
10620 if (dur_msec < required_end) // FIXME
10622 debug_log("invalid end pos for pcm extraction");
10623 return MM_ERROR_INVALID_ARGUMENT;
10626 start_nsec = required_start * G_GINT64_CONSTANT(1000000);
10627 end_nsec = required_end * G_GINT64_CONSTANT(1000000);
10629 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10632 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10633 GST_SEEK_TYPE_SET, start_nsec,
10634 GST_SEEK_TYPE_SET, end_nsec)))
10636 debug_error("failed to seek for pcm extraction\n");
10638 return MM_ERROR_PLAYER_SEEK;
10641 debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
10645 return MM_ERROR_NONE;
10649 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
10651 mm_player_t* player = (mm_player_t*)hplayer;
10652 gint64 cur_pos = 0;
10653 GstFormat fmt = GST_FORMAT_TIME;
10658 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10660 player->section_repeat = FALSE;
10662 __mmplayer_set_play_count( player, onetime );
10664 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
10666 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10669 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10670 GST_SEEK_TYPE_SET, cur_pos,
10671 GST_SEEK_TYPE_SET, player->duration )))
10673 debug_error("failed to deactivate section repeat\n");
10675 return MM_ERROR_PLAYER_SEEK;
10680 return MM_ERROR_NONE;
10684 _mmplayer_set_playspeed(MMHandleType hplayer, float rate)
10686 mm_player_t* player = (mm_player_t*)hplayer;
10687 signed long long pos_msec = 0;
10688 int ret = MM_ERROR_NONE;
10690 GstFormat format =GST_FORMAT_TIME;
10691 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
10694 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
10695 return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
10697 /* The sound of video is not supported under 0.0 and over 2.0. */
10698 if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
10700 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
10703 _mmplayer_set_mute(hplayer, mute);
10705 if (player->playback_rate == rate)
10706 return MM_ERROR_NONE;
10708 /* If the position is reached at start potion during fast backward, EOS is posted.
10709 * So, This EOS have to be classified with it which is posted at reaching the end of stream.
10711 player->playback_rate = rate;
10713 current_state = MMPLAYER_CURRENT_STATE(player);
10715 if ( current_state != MM_PLAYER_STATE_PAUSED )
10716 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
10718 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
10720 if ( ( current_state == MM_PLAYER_STATE_PAUSED )
10722 //|| ( player->last_position != 0 && pos_msec == 0 ) )
10724 debug_warning("returning last point : %lld\n", player->last_position );
10725 pos_msec = player->last_position;
10728 if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
10731 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
10732 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
10733 GST_SEEK_TYPE_SET, pos_msec,
10734 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
10735 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
10737 debug_error("failed to set speed playback\n");
10738 return MM_ERROR_PLAYER_SEEK;
10741 debug_log("succeeded to set speed playback as %0.1f\n", rate);
10745 return MM_ERROR_NONE;;
10749 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
10751 mm_player_t* player = (mm_player_t*)hplayer;
10752 int ret = MM_ERROR_NONE;
10756 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10758 ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
10766 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
10768 mm_player_t* player = (mm_player_t*)hplayer;
10769 int ret = MM_ERROR_NONE;
10771 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10773 ret = __gst_get_position ( player, format, position );
10779 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
10781 mm_player_t* player = (mm_player_t*)hplayer;
10782 int ret = MM_ERROR_NONE;
10784 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10786 ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
10792 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
10794 mm_player_t* player = (mm_player_t*)hplayer;
10795 int ret = MM_ERROR_NONE;
10799 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
10801 ret = __gst_adjust_subtitle_position(player, format, position);
10809 __mmplayer_is_midi_type( gchar* str_caps)
10811 if ( ( g_strrstr(str_caps, "audio/midi") ) ||
10812 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
10813 ( g_strrstr(str_caps, "application/x-smaf") ) ||
10814 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
10815 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
10816 ( g_strrstr(str_caps, "audio/xmf") ) ||
10817 ( g_strrstr(str_caps, "audio/mxmf") ) )
10819 debug_log("midi\n");
10828 __mmplayer_is_only_mp3_type (gchar *str_caps)
10830 if (g_strrstr(str_caps, "application/x-id3") ||
10831 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
10838 /* try to use ALP decoder first instead of selected decoder */
10840 __mmplayer_is_omx_decoder_type (mm_player_t* player)
10842 #define MIN_THRESHOLD_SIZE 320 * 1024 // 320K
10843 gboolean ret = FALSE;
10844 gchar* path = NULL;
10845 guint64 data_size = 0;
10848 return_val_if_fail (player, FALSE);
10850 /* consider mp3 audio only */
10851 if ((!MMPLAYER_IS_STREAMING(player)) &&
10852 (__mmplayer_is_only_mp3_type(player->type)))
10854 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
10856 if (stat(path, &sb) == 0)
10858 data_size = (guint64)sb.st_size;
10860 if (data_size > MIN_THRESHOLD_SIZE)
10867 debug_log ("need to select omx_decoder ? [%s]\n", (ret)?"YES":"NO");
10872 __mmplayer_set_audio_attrs (mm_player_t* player, GstCaps* caps)
10874 GstStructure* caps_structure = NULL;
10875 gint samplerate = 0;
10879 return_if_fail (player && caps);
10881 caps_structure = gst_caps_get_structure(caps, 0);
10883 /* set stream information */
10884 gst_structure_get_int (caps_structure, "rate", &samplerate);
10885 mm_attrs_set_int_by_name (player->attrs, "content_audio_samplerate", samplerate);
10887 gst_structure_get_int (caps_structure, "channels", &channels);
10888 mm_attrs_set_int_by_name (player->attrs, "content_audio_channels", channels);
10890 debug_log ("audio samplerate : %d channels : %d\n", samplerate, channels);
10894 __mmplayer_typefind_have_type( GstElement *tf, guint probability, // @
10895 GstCaps *caps, gpointer data)
10897 mm_player_t* player = (mm_player_t*)data;
10898 GstPad* pad = NULL;
10902 return_if_fail( player && tf && caps );
10904 /* store type string */
10905 MMPLAYER_FREEIF(player->type);
10906 player->type = gst_caps_to_string(caps);
10908 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
10910 if ( (!MMPLAYER_IS_WFD_STREAMING( player )) &&
10911 (!MMPLAYER_IS_RTSP_STREAMING( player )) &&
10912 (g_strrstr(player->type, "audio/x-raw-int")))
10914 debug_error("not support media format\n");
10916 if (player->msg_posted == FALSE)
10918 MMMessageParamType msg_param;
10919 memset (&msg_param, 0, sizeof(MMMessageParamType));
10921 msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
10922 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
10924 /* don't post more if one was sent already */
10925 player->msg_posted = TRUE;
10930 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
10931 if ( __mmplayer_is_midi_type(player->type))
10933 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
10934 player->bypass_audio_effect = TRUE;
10936 else if ( g_strrstr(player->type, "application/x-hls"))
10938 /* If it can't know exact type when it parses uri because of redirection case,
10939 * it will be fixed by typefinder here.
10941 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
10943 else if ( g_strrstr(player->type, "application/dash+xml"))
10945 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
10948 pad = gst_element_get_static_pad(tf, "src");
10951 debug_error("fail to get typefind src pad.\n");
10955 if (player->use_decodebin)
10957 if(!__mmplayer_try_to_plug_decodebin( player, pad, caps ))
10959 gboolean async = FALSE;
10960 debug_error("failed to autoplug %s\n", player->type);
10962 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10964 if ( async && player->msg_posted == FALSE )
10966 __mmplayer_handle_missed_plugin( player );
10975 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
10977 gboolean async = FALSE;
10978 debug_error("failed to autoplug %s\n", player->type);
10980 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
10982 if ( async && player->msg_posted == FALSE )
10984 __mmplayer_handle_missed_plugin( player );
10990 /* finish autopluging if no dynamic pad waiting */
10991 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
10993 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
10995 __mmplayer_pipeline_complete( NULL, (gpointer)player );
11001 gst_object_unref( GST_OBJECT(pad) );
11008 #ifdef _MM_PLAYER_ALP_PARSER
11009 void check_name (void *data, void *user_data)
11011 mm_player_t* player = user_data;
11013 if (g_strrstr((gchar*)data, "mpegaudioparse"))
11015 debug_log("mpegaudioparse - set alp-mp3dec\n");
11016 g_object_set(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "alp-mp3dec", TRUE, NULL);
11021 static GstElement *
11022 __mmplayer_create_decodebin (mm_player_t* player)
11024 GstElement *decodebin = NULL;
11028 /* create decodebin */
11029 decodebin = gst_element_factory_make("decodebin2", "decodebin2");
11033 debug_error("fail to create decodebin\n");
11037 /* raw pad handling signal */
11038 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11039 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
11041 /* no-more-pad pad handling signal */
11042 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
11043 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
11045 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
11046 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
11048 /* This signal is emitted when a pad for which there is no further possible
11049 decoding is added to the decodebin.*/
11050 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
11051 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player );
11053 /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11054 before looking for any elements that can handle that stream.*/
11055 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
11056 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
11058 /* This signal is emitted whenever decodebin2 finds a new stream. It is emitted
11059 before looking for any elements that can handle that stream.*/
11060 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
11061 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
11063 /* Once decodebin2 has found the possible GstElementFactory objects to try for
11064 caps on pad, this signal is emited. The purpose of the signal is for the
11065 application to perform additional sorting or filtering on the element factory
11067 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
11068 G_CALLBACK(__mmplayer_gst_decode_autoplug_sort), player);
11070 /* This signal is emitted once decodebin2 has finished decoding all the data.*/
11071 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
11072 G_CALLBACK(__mmplayer_gst_decode_drained), player);
11074 /* This signal is emitted when a element is added to the bin.*/
11075 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
11076 G_CALLBACK(__mmplayer_gst_element_added), player);
11083 __mmplayer_gst_id3_pad_added(GstElement *element, GstPad *pad, gpointer data)
11085 mm_player_t* player = (mm_player_t*)data;
11086 GstCaps *caps = NULL;
11087 gchar *caps_str = NULL;
11090 return_if_fail (player && pad);
11092 caps = gst_pad_get_caps(pad);
11093 caps_str = gst_caps_to_string(caps);
11095 debug_log("pad %s:%s, caps %s", GST_DEBUG_PAD_NAME(pad), caps_str);
11096 __mmplayer_try_to_plug_decodebin(player, pad, caps);
11098 MMPLAYER_FREEIF( caps_str );
11099 gst_caps_unref(caps);
11105 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
11107 MMPlayerGstElement* mainbin = NULL;
11108 GstElement* decodebin2 = NULL;
11109 GstElement* queue2 = NULL;
11110 GstElement* id3demux = NULL;
11112 GstPad* sinkpad = NULL;
11113 GstPad* qsrcpad= NULL;
11114 gchar *caps_str = NULL;
11116 GstFormat fmt = GST_FORMAT_BYTES;
11117 gint64 dur_bytes = 0L;
11118 gchar* file_buffering_path = NULL;
11119 gboolean use_file_buffer = FALSE;
11121 guint max_buffer_size_bytes = 0;
11122 gdouble init_buffering_time = (gdouble)player->streamer->buffering_req.initial_second;
11125 return_val_if_fail (player && player->pipeline && player->pipeline->mainbin, FALSE);
11127 mainbin = player->pipeline->mainbin;
11129 if ((!MMPLAYER_IS_HTTP_PD(player)) &&
11130 (MMPLAYER_IS_HTTP_STREAMING(player)))
11132 debug_log ("creating http streaming buffering queue (queue2)\n");
11134 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
11136 debug_error ("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
11140 if (!mainbin[MMPLAYER_M_ID3DEMUX].gst)
11142 caps_str = gst_caps_to_string(caps);
11143 if (g_strrstr(caps_str, "application/x-id3"))
11145 debug_log("create id3demux in front of queue2 \n");
11147 id3demux = gst_element_factory_make ("id3demux", NULL);
11150 debug_error ("failed to create buffering id3demux element\n");
11154 MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(id3demux), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
11155 G_CALLBACK(__mmplayer_gst_id3_pad_added), player);
11157 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux))
11159 debug_error("failed to add id3demux\n");
11163 sinkpad = gst_element_get_static_pad(id3demux, "sink");
11165 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11167 debug_error("failed to link buffering queue\n");
11171 if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (id3demux))
11173 debug_error("failed to sync id3demux state with parent\n");
11177 mainbin[MMPLAYER_M_ID3DEMUX].id = MMPLAYER_M_ID3DEMUX;
11178 mainbin[MMPLAYER_M_ID3DEMUX].gst = id3demux;
11180 gst_object_unref(GST_OBJECT(sinkpad));
11181 MMPLAYER_FREEIF( caps_str );
11187 MMPLAYER_FREEIF( caps_str );
11190 queue2 = gst_element_factory_make ("queue2", "queue2");
11193 debug_error ("failed to create buffering queue element\n");
11197 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2))
11199 debug_error("failed to add buffering queue\n");
11203 sinkpad = gst_element_get_static_pad(queue2, "sink");
11204 qsrcpad = gst_element_get_static_pad(queue2, "src");
11206 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11208 debug_error("failed to link buffering queue\n");
11212 // if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
11214 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
11215 debug_error("fail to get duration.\n");
11217 debug_log("dur_bytes = %lld\n", dur_bytes);
11221 use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
11222 file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
11230 /* NOTE : we cannot get any duration info from ts container in case of streaming */
11231 // if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
11232 if(!g_strrstr(player->type, "video/mpegts"))
11234 max_buffer_size_bytes = (use_file_buffer)?(player->ini.http_max_size_bytes):(5*1024*1024);
11235 debug_log("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
11237 __mm_player_streaming_set_queue2(player->streamer,
11240 max_buffer_size_bytes,
11241 player->ini.http_buffering_time,
11243 player->ini.http_buffering_limit, // no meaning
11245 file_buffering_path,
11246 (guint64)dur_bytes);
11249 MMPLAYER_FREEIF(file_buffering_path);
11250 if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (queue2))
11252 debug_error("failed to sync queue2 state with parent\n");
11258 gst_object_unref(GST_OBJECT(sinkpad));
11260 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
11261 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
11265 /* create decodebin */
11266 decodebin2 = __mmplayer_create_decodebin(player);
11270 debug_error("can not create autoplug element\n");
11274 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2))
11276 debug_error("failed to add decodebin2\n");
11280 /* to force caps on the decodebin element and avoid reparsing stuff by
11281 * typefind. It also avoids a deadlock in the way typefind activates pads in
11282 * the state change */
11283 g_object_set (decodebin2, "sink-caps", caps, NULL);
11285 sinkpad = gst_element_get_static_pad(decodebin2, "sink");
11287 if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad))
11289 debug_error("failed to link decodebin2\n");
11293 gst_object_unref(GST_OBJECT(sinkpad));
11295 mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
11296 mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin2;
11298 if ( ((!MMPLAYER_IS_HTTP_PD(player)) &&
11299 (MMPLAYER_IS_HTTP_STREAMING(player))) || MMPLAYER_IS_DASH_STREAMING (player))
11301 init_buffering_time = (init_buffering_time != 0)?(init_buffering_time):(player->ini.http_buffering_time);
11303 g_object_set (G_OBJECT(decodebin2), "use-buffering", TRUE,
11304 "high-percent", (gint)player->ini.http_buffering_limit,
11305 "low-percent", 1, // 1%
11306 "max-size-bytes", MAX_DECODEBIN_BUFFER_BYTES,
11307 "max-size-time", (guint64)(MAX_DECODEBIN_BUFFER_TIME * GST_SECOND),
11308 "max-size-buffers", 0, NULL); // disable or automatic
11311 if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin2))
11313 debug_error("failed to sync decodebin2 state with parent\n");
11323 MMPLAYER_FREEIF( caps_str );
11326 gst_object_unref(GST_OBJECT(sinkpad));
11330 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11331 * You need to explicitly set elements to the NULL state before
11332 * dropping the final reference, to allow them to clean up.
11334 gst_element_set_state(queue2, GST_STATE_NULL);
11336 /* And, it still has a parent "player".
11337 * You need to let the parent manage the object instead of unreffing the object directly.
11339 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
11340 gst_object_unref (queue2);
11346 /* NOTE : Trying to dispose element id3demux, but it is in READY instead of the NULL state.
11347 * You need to explicitly set elements to the NULL state before
11348 * dropping the final reference, to allow them to clean up.
11350 gst_element_set_state(id3demux, GST_STATE_NULL);
11352 /* And, it still has a parent "player".
11353 * You need to let the parent manage the object instead of unreffing the object directly.
11355 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux);
11356 gst_object_unref (id3demux);
11362 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
11363 * You need to explicitly set elements to the NULL state before
11364 * dropping the final reference, to allow them to clean up.
11366 gst_element_set_state(decodebin2, GST_STATE_NULL);
11368 /* And, it still has a parent "player".
11369 * You need to let the parent manage the object instead of unreffing the object directly.
11372 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin2);
11373 gst_object_unref (decodebin2);
11380 /* it will return first created element */
11382 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
11384 MMPlayerGstElement* mainbin = NULL;
11385 const char* mime = NULL;
11386 const GList* item = NULL;
11387 const gchar* klass = NULL;
11388 GstCaps* res = NULL;
11389 gboolean skip = FALSE;
11390 GstPad* queue_pad = NULL;
11391 GstElement* queue = NULL;
11392 GstElement *element = NULL;
11396 return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
11398 mainbin = player->pipeline->mainbin;
11400 mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
11402 /* return if we got raw output */
11403 if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
11404 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
11407 element = (GstElement*)gst_pad_get_parent(pad);
11408 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
11409 * No queue will be added. I think it can caused breaking sound when playing raw audio
11410 * frames but there's no different. Decodebin also doesn't add with those wav fils.
11411 * Anyway, currentely raw-queue seems not necessary.
11414 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
11415 * has linked. if so, we need to add queue for quality of output. note that
11416 * decodebin also has same problem.
11418 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
11420 /* add queue if needed */
11421 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
11422 || g_strrstr(klass, "Parse")) && !g_str_has_prefix(mime, "text"))
11424 debug_log("adding raw queue\n");
11426 queue = gst_element_factory_make("queue", NULL);
11429 debug_warning("failed to create queue\n");
11434 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
11436 debug_warning("failed to set state READY to queue\n");
11440 /* add to pipeline */
11441 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
11443 debug_warning("failed to add queue\n");
11448 queue_pad = gst_element_get_static_pad(queue, "sink");
11450 if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
11452 debug_warning("failed to link queue\n");
11455 gst_object_unref ( GST_OBJECT(queue_pad) );
11459 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
11461 debug_warning("failed to set state READY to queue\n");
11465 /* replace given pad to queue:src */
11466 pad = gst_element_get_static_pad(queue, "src");
11469 debug_warning("failed to get pad from queue\n");
11474 /* check if player can do start continually */
11475 MMPLAYER_CHECK_CMD_IF_EXIT(player);
11477 if(__mmplayer_link_sink(player,pad))
11478 __mmplayer_gst_decode_callback(element, pad, player);
11480 gst_object_unref( GST_OBJECT(element));
11486 item = player->factories;
11487 for(; item != NULL ; item = item->next)
11489 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
11495 /* filtering exclude keyword */
11496 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
11498 if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
11499 player->ini.exclude_element_keyword[idx] ) )
11501 debug_warning("skipping [%s] by exculde keyword [%s]\n",
11502 GST_PLUGIN_FEATURE_NAME (factory),
11503 player->ini.exclude_element_keyword[idx] );
11510 if ( MMPLAYER_IS_RTSP_STREAMING(player) && g_strrstr(GST_PLUGIN_FEATURE_NAME (factory), "omx_mpeg4dec"))
11512 // omx decoder can not support mpeg4video data partitioned
11513 // rtsp streaming didn't know mpeg4video data partitioned format
11514 // so, if rtsp playback, player will skip omx_mpeg4dec.
11515 debug_warning("skipping [%s] when rtsp streaming \n",
11516 GST_PLUGIN_FEATURE_NAME (factory));
11521 if ( skip ) continue;
11523 /* check factory class for filtering */
11524 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
11526 /* NOTE : msl don't need to use image plugins.
11527 * So, those plugins should be skipped for error handling.
11529 if ( g_strrstr(klass, "Codec/Decoder/Image") )
11531 debug_log("skipping [%s] by not required\n", GST_PLUGIN_FEATURE_NAME (factory));
11535 /* check pad compatability */
11536 for(pads = gst_element_factory_get_static_pad_templates(factory);
11537 pads != NULL; pads=pads->next)
11539 GstStaticPadTemplate *temp1 = pads->data;
11540 GstCaps* static_caps = NULL;
11542 if( temp1->direction != GST_PAD_SINK ||
11543 temp1->presence != GST_PAD_ALWAYS)
11546 if ( GST_IS_CAPS( &temp1->static_caps.caps) )
11548 /* using existing caps */
11549 static_caps = gst_caps_ref( &temp1->static_caps.caps );
11554 static_caps = gst_caps_from_string ( temp1->static_caps.string );
11557 res = gst_caps_intersect(caps, static_caps);
11559 gst_caps_unref( static_caps );
11560 static_caps = NULL;
11562 if( res && !gst_caps_is_empty(res) )
11564 GstElement *new_element;
11565 GList *elements = player->parsers;
11566 char *name_template = g_strdup(temp1->name_template);
11567 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
11568 gst_caps_unref(res);
11570 /* check ALP Codec can be used or not */
11571 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
11573 /* consider mp3 audio only */
11574 if ( !MMPLAYER_IS_STREAMING(player) && __mmplayer_is_only_mp3_type(player->type) )
11576 /* try to use ALP decoder first instead of selected decoder */
11577 GstElement *element = NULL;
11578 GstElementFactory * element_facory;
11579 gchar *path = NULL;
11580 guint64 data_size = 0;
11581 #define MIN_THRESHOLD_SIZE 320 * 1024 // 320K
11584 mm_attrs_get_string_by_name(player->attrs, "profile_uri", &path);
11586 if (stat(path, &sb) == 0)
11588 data_size = (guint64)sb.st_size;
11590 debug_log("file size : %u", data_size);
11592 if (data_size > MIN_THRESHOLD_SIZE)
11594 debug_log("checking if ALP can be used or not");
11595 element = gst_element_factory_make("omx_mp3dec", "omx mp3 decoder");
11598 /* check availability because multi-instance is not supported */
11599 GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY);
11601 if (ret != GST_STATE_CHANGE_SUCCESS) // use just selected decoder
11603 gst_object_unref (element);
11605 else if (ret == GST_STATE_CHANGE_SUCCESS) // replace facotry to use omx
11608 gst_element_set_state(element, GST_STATE_NULL);
11609 gst_object_unref (element);
11611 element_facory = gst_element_factory_find("omx_mp3dec");
11612 /* replace, otherwise use selected thing instead */
11613 if (element_facory)
11615 factory = element_facory;
11616 name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
11619 /* make parser alp mode */
11620 #ifdef _MM_PLAYER_ALP_PARSER
11621 g_list_foreach (player->parsers, check_name, player);
11628 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
11630 if ( g_strrstr(GST_PLUGIN_FEATURE_NAME(factory), "omx_") )
11632 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
11635 if (strncasecmp(env, "yes", 3) == 0)
11637 debug_log("skipping [%s] by disabled\n", name_to_plug);
11638 MMPLAYER_FREEIF(name_template);
11645 debug_log("found %s to plug\n", name_to_plug);
11647 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
11648 if ( ! new_element )
11650 debug_error("failed to create element [%s]. continue with next.\n",
11651 GST_PLUGIN_FEATURE_NAME (factory));
11653 MMPLAYER_FREEIF(name_template);
11658 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
11659 * because parser can accept its own output as input.
11661 if (g_strrstr(klass, "Parser"))
11663 gchar *selected = NULL;
11665 for ( ; elements; elements = g_list_next(elements))
11667 gchar *element_name = elements->data;
11669 if (g_strrstr(element_name, name_to_plug))
11671 debug_log("but, %s already linked, so skipping it\n", name_to_plug);
11678 MMPLAYER_FREEIF(name_template);
11682 selected = g_strdup(name_to_plug);
11683 player->parsers = g_list_append(player->parsers, selected);
11686 /* store specific handles for futher control */
11687 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
11689 /* FIXIT : first value will be overwritten if there's more
11690 * than 1 demuxer/parser
11692 debug_log("plugged element is demuxer. take it\n");
11693 mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11694 mainbin[MMPLAYER_M_DEMUX].gst = new_element;
11696 /*Added for multi audio support */
11697 if(g_strrstr(klass, "Demux"))
11699 mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11700 mainbin[MMPLAYER_M_DEMUX_EX].gst = new_element;
11702 /* NOTE : workaround for bug in mpegtsdemux since doesn't emit
11703 no-more-pad signal. this may cause wrong content attributes at PAUSED state
11704 this code should be removed after mpegtsdemux is fixed */
11705 if ( g_strrstr(GST_PLUGIN_FEATURE_NAME(factory), "mpegtsdemux") )
11707 debug_warning("force no-more-pad to TRUE since mpegtsdemux os not giving no-more-pad signal. content attributes may wrong");
11708 player->no_more_pad = TRUE;
11711 if (g_strrstr(name_to_plug, "asfdemux")) // to support trust-zone only
11713 g_object_set(mainbin[MMPLAYER_M_DEMUX_EX].gst, "file-location", player->profile.uri,NULL);
11716 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
11718 if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
11720 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
11721 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
11722 mainbin[MMPLAYER_M_DEC1].gst = new_element;
11724 else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
11726 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
11727 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
11728 mainbin[MMPLAYER_M_DEC2].gst = new_element;
11730 /* NOTE : IF one codec is found, add it to supported_codec and remove from
11731 * missing plugin. Both of them are used to check what's supported codec
11732 * before returning result of play start. And, missing plugin should be
11733 * updated here for multi track files.
11735 if(g_str_has_prefix(mime, "video"))
11737 GstPad *src_pad = NULL;
11738 GstPadTemplate *pad_templ = NULL;
11739 GstCaps *caps = NULL;
11740 gchar *caps_str = NULL;
11742 debug_log("found VIDEO decoder\n");
11743 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
11744 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
11746 src_pad = gst_element_get_static_pad (new_element, "src");
11747 pad_templ = gst_pad_get_pad_template (src_pad);
11748 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
11750 caps_str = gst_caps_to_string(caps);
11753 MMPLAYER_FREEIF( caps_str );
11754 gst_object_unref (src_pad);
11756 else if (g_str_has_prefix(mime, "audio"))
11758 debug_log("found AUDIO decoder\n");
11759 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
11760 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
11764 if ( ! __mmplayer_close_link(player, pad, new_element,
11765 name_template,gst_element_factory_get_static_pad_templates(factory)) )
11767 MMPLAYER_FREEIF(name_template);
11768 if (player->keep_detecting_vcodec)
11771 /* Link is failed even though a supportable codec is found. */
11772 __mmplayer_check_not_supported_codec(player, klass, mime);
11774 debug_error("failed to call _close_link\n");
11778 MMPLAYER_FREEIF(name_template);
11782 gst_caps_unref(res);
11787 /* There is no available codec. */
11788 __mmplayer_check_not_supported_codec(player, klass, mime);
11796 gst_object_unref( queue );
11799 gst_object_unref( queue_pad );
11802 gst_object_unref ( element );
11809 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
11813 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
11814 return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
11816 debug_log("class : %s, mime : %s \n", factory_class, mime );
11818 /* add missing plugin */
11819 /* NOTE : msl should check missing plugin for image mime type.
11820 * Some motion jpeg clips can have playable audio track.
11821 * So, msl have to play audio after displaying popup written video format not supported.
11823 if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
11825 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
11827 debug_log("not found demuxer\n");
11828 player->not_found_demuxer = TRUE;
11829 player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
11835 if( !g_strrstr(factory_class, "Demuxer"))
11837 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
11839 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
11840 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
11842 /* check that clip have multi tracks or not */
11843 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
11845 debug_log("video plugin is already linked\n");
11849 debug_warning("add VIDEO to missing plugin\n");
11850 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
11853 else if ( g_str_has_prefix(mime, "audio") )
11855 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
11857 debug_log("audio plugin is already linked\n");
11861 debug_warning("add AUDIO to missing plugin\n");
11862 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
11870 return MM_ERROR_NONE;
11875 __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data)
11877 mm_player_t* player = (mm_player_t*)data;
11881 return_if_fail( player );
11883 /* remove fakesink. */
11884 if ( ! __mmplayer_gst_remove_fakesink( player,
11885 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
11887 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
11888 * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
11889 * source element are not same. To overcome this situation, this function will called
11890 * several places and several times. Therefore, this is not an error case.
11895 debug_log("pipeline has completely constructed\n");
11897 if ( ( player->ini.async_start ) &&
11898 ( player->msg_posted == FALSE ) &&
11899 ( player->cmd >= MMPLAYER_COMMAND_START ))
11901 __mmplayer_handle_missed_plugin( player );
11904 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
11908 __mmplayer_verify_next_play_path(mm_player_t *player)
11910 MMHandleType attrs = 0;
11911 MMPlayerParseProfile profile;
11912 gint uri_idx = 0, check_cnt = 0;
11914 gint mode = MM_PLAYER_PD_MODE_NONE;
11916 guint num_of_list = 0;
11920 debug_log("checking for next play");
11922 if (player->pipeline->textbin)
11924 debug_error("subtitle path is enabled. next play is not supported.\n");
11928 attrs = MMPLAYER_GET_ATTRS(player);
11931 debug_error("fail to get attributes.\n");
11935 /* seamless playback is supported in case of audio only */
11936 mm_attrs_get_int_by_name(attrs, "content_video_found", &mode);
11939 debug_log("video found");
11943 if (mm_attrs_get_int_by_name (attrs, "pd_mode", &mode) == MM_ERROR_NONE)
11947 debug_warning("pd mode\n");
11952 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
11954 debug_error("can not get play count\n");
11957 num_of_list = g_list_length(player->uri_info.uri_list);
11959 debug_log("repeat count = %d, num_of_list = %d\n", count, num_of_list);
11961 if ( num_of_list == 0 )
11963 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE)
11965 debug_error("can not get profile_uri\n");
11971 debug_error("uri list is empty.\n");
11975 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
11976 debug_log("add original path : %s ", uri);
11982 uri_idx = player->uri_info.uri_idx;
11988 if (check_cnt > num_of_list)
11990 debug_error("there is no valid uri.");
11994 debug_log("uri idx : %d / %d\n", uri_idx, num_of_list);
11996 if ( uri_idx < num_of_list-1 )
12002 if ((count <= 1) && (count != -1))
12004 debug_log("no repeat.");
12007 else if ( count > 1 ) /* decrease play count */
12009 /* we successeded to rewind. update play count and then wait for next EOS */
12012 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
12014 /* commit attribute */
12015 if ( mmf_attrs_commit ( attrs ) )
12017 debug_error("failed to commit attribute\n");
12021 /* count < 0 : repeat continually */
12025 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12026 debug_log("uri idx : %d, uri = %s\n", uri_idx, uri);
12030 debug_warning("next uri does not exist\n");
12034 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE)
12036 debug_error("failed to parse profile\n");
12040 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
12041 (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP))
12043 debug_warning("uri type is not supported (%d).", profile.uri_type);
12050 player->uri_info.uri_idx = uri_idx;
12051 mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12054 if (mmf_attrs_commit(player->attrs))
12056 debug_error("failed to commit.\n");
12060 debug_log("next uri %s (%d)\n", uri, uri_idx);
12066 debug_error("unable to play next path. EOS will be posted soon.\n");
12071 __mmplayer_initialize_next_play(mm_player_t *player)
12077 player->needed_v_parser = FALSE;
12078 player->smooth_streaming = FALSE;
12079 player->videodec_linked = 0;
12080 player->audiodec_linked = 0;
12081 player->videosink_linked = 0;
12082 player->audiosink_linked = 0;
12083 player->textsink_linked = 0;
12084 player->is_external_subtitle_present = FALSE;
12085 player->not_supported_codec = MISSING_PLUGIN_NONE;
12086 player->can_support_codec = FOUND_PLUGIN_NONE;
12087 player->pending_seek.is_pending = FALSE;
12088 player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
12089 player->pending_seek.pos = 0;
12090 player->msg_posted = FALSE;
12091 player->has_many_types = FALSE;
12092 player->no_more_pad = FALSE;
12093 player->is_drm_file = FALSE;
12094 player->not_found_demuxer = 0;
12095 player->doing_seek = FALSE;
12096 player->max_audio_channels = 0;
12097 player->is_subtitle_force_drop = FALSE;
12098 player->play_subtitle = FALSE;
12099 player->use_textoverlay = FALSE;
12100 player->adjust_subtitle_pos = 0;
12102 player->updated_bitrate_count = 0;
12103 player->total_bitrate = 0;
12104 player->updated_maximum_bitrate_count = 0;
12105 player->total_maximum_bitrate = 0;
12107 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
12109 player->bitrate[i] = 0;
12110 player->maximum_bitrate[i] = 0;
12113 if (player->v_stream_caps)
12115 gst_caps_unref(player->v_stream_caps);
12116 player->v_stream_caps = NULL;
12119 mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
12120 mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
12122 /* clean found parsers */
12123 if (player->parsers)
12125 GList *parsers = player->parsers;
12126 for ( ;parsers ; parsers = g_list_next(parsers))
12128 gchar *name = parsers->data;
12129 MMPLAYER_FREEIF(name);
12131 g_list_free(player->parsers);
12132 player->parsers = NULL;
12135 /* clean found audio decoders */
12136 if (player->audio_decoders)
12138 GList *a_dec = player->audio_decoders;
12139 for ( ;a_dec ; a_dec = g_list_next(a_dec))
12141 gchar *name = a_dec->data;
12142 MMPLAYER_FREEIF(name);
12144 g_list_free(player->audio_decoders);
12145 player->audio_decoders = NULL;
12152 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
12154 MMPlayerGstElement *mainbin = NULL;
12155 MMMessageParamType msg_param = {0,};
12156 GstElement *element = NULL;
12157 MMHandleType attrs = 0;
12159 enum MainElementID elemId = MMPLAYER_M_NUM;
12163 if ((player->pipeline == NULL) ||
12164 (player->pipeline->mainbin == NULL))
12166 debug_error("player is null.\n");
12170 mainbin = player->pipeline->mainbin;
12171 msg_param.code = MM_ERROR_PLAYER_INTERNAL;
12173 attrs = MMPLAYER_GET_ATTRS(player);
12176 debug_error("fail to get attributes.\n");
12180 /* Initialize Player values */
12181 __mmplayer_initialize_next_play(player);
12183 mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
12185 if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE)
12187 debug_error("failed to parse profile\n");
12188 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12192 if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
12193 (MMPLAYER_URL_HAS_HLS_SUFFIX(player)))
12195 debug_error("it's dash or hls. not support.");
12196 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
12201 switch ( player->profile.uri_type )
12204 case MM_PLAYER_URI_TYPE_FILE:
12207 #ifdef ENABLE_DRMSRC
12209 char* drmsrc = player->ini.name_of_drmsrc;
12211 debug_log("using [%s] for 'file://' handler.\n", drmsrc);
12213 element = gst_element_factory_make(drmsrc, "source");
12216 debug_error("failed to create %s\n", drmsrc);
12220 debug_log("using filesrc for 'file://' handler.\n");
12222 element = gst_element_factory_make("filesrc", "source");
12226 debug_error("failed to create filesrc\n");
12230 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
12233 case MM_PLAYER_URI_TYPE_URL_HTTP:
12235 gchar *user_agent, *proxy, *cookies, **cookie_list;
12236 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
12237 user_agent = proxy = cookies = NULL;
12238 cookie_list = NULL;
12240 element = gst_element_factory_make(player->ini.name_of_httpsrc, "http_streaming_source");
12243 debug_error("failed to create http streaming source element[%s].\n", player->ini.name_of_httpsrc);
12246 debug_log("using http streamming source [%s].\n", player->ini.name_of_httpsrc);
12248 /* get attribute */
12249 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
12250 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
12251 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
12252 mm_attrs_get_int_by_name ( attrs, "streaming_timeout", &http_timeout );
12254 if ((http_timeout == DEFAULT_HTTP_TIMEOUT) &&
12255 (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT))
12257 debug_log("get timeout from ini\n");
12258 http_timeout = player->ini.http_timeout;
12261 /* get attribute */
12262 secure_debug_log("location : %s\n", player->profile.uri);
12263 secure_debug_log("cookies : %s\n", cookies);
12264 secure_debug_log("proxy : %s\n", proxy);
12265 secure_debug_log("user_agent : %s\n", user_agent);
12266 debug_log("timeout : %d\n", http_timeout);
12268 /* setting property to streaming source */
12269 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
12270 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
12271 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
12273 /* check if prosy is vailid or not */
12274 if ( util_check_valid_url ( proxy ) )
12275 g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
12276 /* parsing cookies */
12277 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
12278 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
12280 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
12284 debug_error("not support uri type %d\n", player->profile.uri_type);
12290 debug_error("no source element was created.\n");
12294 if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12296 debug_error("failed to add source element to pipeline\n");
12297 gst_object_unref(GST_OBJECT(element));
12302 /* take source element */
12303 mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
12304 mainbin[MMPLAYER_M_SRC].gst = element;
12308 if (MMPLAYER_IS_HTTP_STREAMING(player))
12310 if (player->streamer == NULL)
12312 player->streamer = __mm_player_streaming_create();
12314 if(player->streamer == NULL)
12317 __mm_player_streaming_initialize(player->streamer);
12320 elemId = MMPLAYER_M_TYPEFIND;
12321 element = gst_element_factory_make("typefind", "typefinder");
12322 MMPLAYER_SIGNAL_CONNECT( player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
12323 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
12327 elemId = MMPLAYER_M_AUTOPLUG;
12328 element = __mmplayer_create_decodebin(player);
12331 /* check autoplug element is OK */
12334 debug_error("can not create element (%d)\n", elemId);
12338 if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE)
12340 debug_error("failed to add sinkbin to pipeline\n");
12341 gst_object_unref(GST_OBJECT(element));
12346 mainbin[elemId].id = elemId;
12347 mainbin[elemId].gst = element;
12349 if ( gst_element_link (mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE )
12351 debug_error("Failed to link src - autoplug (or typefind)\n");
12355 if (gst_element_set_state (mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE)
12357 debug_error("Failed to change state of src element\n");
12361 if (!MMPLAYER_IS_HTTP_STREAMING(player))
12363 if (gst_element_set_state (mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE)
12365 debug_error("Failed to change state of decodebin2\n");
12371 if (gst_element_set_state (mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE)
12373 debug_error("Failed to change state of src element\n");
12378 player->src_changed = TRUE;
12384 MMPLAYER_PLAYBACK_UNLOCK(player);
12386 if (!player->msg_posted)
12388 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
12389 player->msg_posted = TRUE;
12395 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
12397 mm_player_selector_t *selector = &player->selector[type];
12398 MMPlayerGstElement *sinkbin = NULL;
12399 enum MainElementID selectorId = MMPLAYER_M_NUM;
12400 enum MainElementID sinkId = MMPLAYER_M_NUM;
12401 GstPad *srcpad = NULL;
12402 GstPad *sinkpad = NULL;
12405 return_val_if_fail (player, FALSE);
12407 debug_log("type %d", type);
12411 case MM_PLAYER_TRACK_TYPE_VIDEO:
12412 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
12413 sinkId = MMPLAYER_V_BIN;
12414 sinkbin = player->pipeline->videobin;
12416 case MM_PLAYER_TRACK_TYPE_AUDIO:
12417 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
12418 sinkId = MMPLAYER_A_BIN;
12419 sinkbin = player->pipeline->audiobin;
12421 case MM_PLAYER_TRACK_TYPE_TEXT:
12422 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
12423 sinkId = MMPLAYER_T_BIN;
12424 sinkbin = player->pipeline->textbin;
12427 debug_error("requested type is not supportable");
12432 if (player->pipeline->mainbin[selectorId].gst)
12436 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
12438 if ((sinkbin) && (sinkbin[sinkId].gst))
12440 sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
12442 if (srcpad && sinkpad)
12444 /* after getting drained signal there is no data flows, so no need to do pad_block */
12445 debug_log("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
12446 gst_pad_unlink (srcpad, sinkpad);
12449 gst_object_unref (sinkpad);
12452 gst_object_unref (srcpad);
12455 debug_log("selector release");
12456 if(selector->channels)
12458 debug_log("release and unref request pads");
12460 /* release and unref requests pad from the selector */
12461 for (n = 0; n < selector->channels->len; n++)
12463 GstPad *sinkpad = g_ptr_array_index (selector->channels, n);
12464 gst_element_release_request_pad ((player->pipeline->mainbin[selectorId].gst), sinkpad);
12466 g_ptr_array_set_size (selector->channels, 0);
12468 gst_element_set_state (player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
12469 gst_bin_remove (GST_BIN_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
12471 player->pipeline->mainbin[selectorId].gst = NULL;
12479 __mmplayer_deactivate_old_path(mm_player_t *player)
12482 return_if_fail ( player );
12484 g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_DEC1].gst), "remove-buffer-signal", TRUE, NULL);
12486 if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
12487 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
12488 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT)))
12490 debug_error("deactivate selector error");
12494 __mmplayer_release_signal_connection( player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG );
12496 if (player->streamer)
12498 __mm_player_streaming_deinitialize (player->streamer);
12499 __mm_player_streaming_destroy(player->streamer);
12500 player->streamer = NULL;
12503 MMPLAYER_PLAYBACK_LOCK(player);
12504 g_cond_signal( player->next_play_thread_cond );
12511 if (!player->msg_posted)
12513 MMMessageParamType msg = {0,};
12516 msg.code = MM_ERROR_PLAYER_INTERNAL;
12517 debug_error("next_uri_play> deactivate error");
12519 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12520 player->msg_posted = TRUE;
12525 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
12527 int result = MM_ERROR_NONE;
12528 mm_player_t* player = (mm_player_t*) hplayer;
12531 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12533 mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
12534 if (mmf_attrs_commit(player->attrs))
12536 debug_error("failed to commit the original uri.\n");
12537 result = MM_ERROR_PLAYER_INTERNAL;
12541 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
12543 debug_error("failed to add the original uri in the uri list.\n");
12551 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
12553 mm_player_t* player = (mm_player_t*) hplayer;
12554 guint num_of_list = 0;
12558 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12559 return_val_if_fail (uri, MM_ERROR_INVALID_ARGUMENT);
12561 if (player->pipeline && player->pipeline->textbin)
12563 debug_error("subtitle path is enabled.\n");
12564 return MM_ERROR_PLAYER_INVALID_STATE;
12567 num_of_list = g_list_length(player->uri_info.uri_list);
12569 if (is_first_path == TRUE)
12571 if (num_of_list == 0)
12573 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12574 debug_log("add original path : %s", uri);
12578 player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
12579 player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
12581 debug_log("change original path : %s", uri);
12586 if (num_of_list == 0)
12588 MMHandleType attrs = 0;
12589 char *original_uri = NULL;
12591 attrs = MMPLAYER_GET_ATTRS(player);
12594 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
12598 debug_error("there is no original uri.");
12599 return MM_ERROR_PLAYER_INVALID_STATE;
12602 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
12603 player->uri_info.uri_idx = 0;
12605 debug_log("add original path at first : %s (%d)", original_uri);
12609 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
12610 debug_log("add new path : %s (total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
12614 return MM_ERROR_NONE;
12617 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
12619 mm_player_t* player = (mm_player_t*) hplayer;
12620 char *next_uri = NULL;
12621 guint num_of_list = 0;
12624 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12626 num_of_list = g_list_length(player->uri_info.uri_list);
12628 if (num_of_list > 0)
12630 gint uri_idx = player->uri_info.uri_idx;
12632 if ( uri_idx < num_of_list-1 )
12637 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
12638 debug_error("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
12640 *uri = g_strdup(next_uri);
12644 return MM_ERROR_NONE;
12648 __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad* pad,
12649 GstCaps *caps, gpointer data)
12651 mm_player_t* player = (mm_player_t*)data;
12652 const gchar* klass = NULL;
12653 const gchar* mime = NULL;
12654 gchar* caps_str = NULL;
12656 klass = gst_element_factory_get_klass (gst_element_get_factory(elem));
12657 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12658 caps_str = gst_caps_to_string(caps);
12660 debug_warning("unknown type of caps : %s from %s",
12661 caps_str, GST_ELEMENT_NAME (elem));
12663 MMPLAYER_FREEIF(caps_str);
12665 /* There is no available codec. */
12666 __mmplayer_check_not_supported_codec (player, klass, mime);
12670 __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad* pad,
12671 GstCaps * caps, gpointer data)
12673 mm_player_t* player = (mm_player_t*)data;
12674 const char* mime = NULL;
12675 gboolean ret = TRUE;
12677 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12678 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12680 if (g_str_has_prefix(mime, "audio")) {
12681 GstStructure* caps_structure = NULL;
12682 gint samplerate = 0;
12684 gchar *caps_str = NULL;
12686 caps_structure = gst_caps_get_structure(caps, 0);
12687 gst_structure_get_int (caps_structure, "rate", &samplerate);
12688 gst_structure_get_int (caps_structure, "channels", &channels);
12690 if ( (channels > 0 && samplerate == 0)) {
12691 debug_log("exclude audio...");
12695 caps_str = gst_caps_to_string(caps);
12696 /* set it directly because not sent by TAG */
12697 if (g_strrstr(caps_str, "mobile-xmf")) {
12698 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
12700 MMPLAYER_FREEIF (caps_str);
12701 } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
12702 debug_log("already video linked");
12705 debug_log("found new stream");
12712 __mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad* pad,
12713 GstCaps* caps, GstElementFactory* factory, gpointer data)
12715 /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
12716 We are defining our own and will be removed when it actually exposed */
12718 GST_AUTOPLUG_SELECT_TRY,
12719 GST_AUTOPLUG_SELECT_EXPOSE,
12720 GST_AUTOPLUG_SELECT_SKIP
12721 } GstAutoplugSelectResult;
12723 GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
12724 mm_player_t* player = (mm_player_t*)data;
12726 gchar* factory_name = NULL;
12727 gchar* caps_str = NULL;
12728 const gchar* klass = NULL;
12731 factory_name = GST_PLUGIN_FEATURE_NAME (factory);
12732 klass = gst_element_factory_get_klass(factory);
12733 caps_str = gst_caps_to_string(caps);
12735 // debug_log("found new element [%s] to link for caps [%s]", factory_name, caps_str);
12736 debug_log("found new element [%s] to link", factory_name);
12738 /* store type string */
12739 if (player->type == NULL)
12741 player->type = gst_caps_to_string(caps);
12743 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
12744 if (__mmplayer_is_midi_type(player->type))
12746 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
12747 player->bypass_audio_effect = TRUE;
12749 else if (g_strrstr(player->type, "application/x-hls"))
12751 /* If it can't know exact type when it parses uri because of redirection case,
12752 * it will be fixed by typefinder here.
12754 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
12756 else if (g_strrstr(player->type, "application/dash+xml"))
12758 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
12762 /* filtering exclude keyword */
12763 for ( idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++ )
12765 if ( strstr(factory_name, player->ini.exclude_element_keyword[idx] ) )
12767 debug_warning("skipping [%s] by exculde keyword [%s]\n",
12768 factory_name, player->ini.exclude_element_keyword[idx] );
12770 // NOTE : does we need to check n_value against the number of item selected?
12771 result = GST_AUTOPLUG_SELECT_SKIP;
12776 /* check factory class for filtering */
12777 /* NOTE : msl don't need to use image plugins.
12778 * So, those plugins should be skipped for error handling.
12780 if (g_strrstr(klass, "Codec/Decoder/Image"))
12782 debug_log("skipping [%s] by not required\n", factory_name);
12783 result = GST_AUTOPLUG_SELECT_SKIP;
12787 if (g_strrstr(factory_name, "mpegpsdemux"))
12789 debug_log("skipping PS container - not support\n");
12790 result = GST_AUTOPLUG_SELECT_SKIP;
12794 if (g_strrstr(factory_name, "mpegtsdemux") || g_strrstr(factory_name, "ssdemux"))
12796 if (g_strrstr(factory_name, "ssdemux"))
12797 player->smooth_streaming = TRUE;
12799 if (g_strrstr(caps_str, "video/x-h264"))
12801 player->needed_v_parser = TRUE;
12803 else if (g_strrstr(caps_str, "video/mpeg"))
12805 player->needed_v_parser = TRUE;
12809 /* check ALP Codec can be used or not */
12810 if ((g_strrstr(klass, "Codec/Decoder/Audio")))
12812 GstStructure* str = NULL;
12815 str = gst_caps_get_structure( caps, 0 );
12818 gst_structure_get_int (str, "channels", &channels);
12820 debug_log ("check audio ch : %d %d\n", player->max_audio_channels, channels);
12821 if (player->max_audio_channels < channels)
12823 player->max_audio_channels = channels;
12827 if (!player->audiodec_linked)
12829 /* set stream information */
12830 __mmplayer_set_audio_attrs (player, caps);
12833 else if ((g_strrstr(klass, "Codec/Decoder/Video")))
12835 if (g_strrstr(factory_name, "omx_"))
12837 char *env = getenv ("MM_PLAYER_HW_CODEC_DISABLE");
12840 if (strncasecmp(env, "yes", 3) == 0)
12842 debug_log ("skipping [%s] by disabled\n", factory_name);
12843 result = GST_AUTOPLUG_SELECT_SKIP;
12850 if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
12851 (g_strrstr(klass, "Codec/Decoder/Video")))
12855 GstStructure *str = NULL;
12856 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
12858 /* don't make video because of not required */
12859 if (stype == MM_DISPLAY_SURFACE_NULL)
12861 debug_log ("no video because it's not required. -> return expose");
12862 if (player->set_mode.media_packet_video_stream == FALSE)
12864 result = GST_AUTOPLUG_SELECT_EXPOSE;
12869 /* get w/h for omx state-tune */
12870 str = gst_caps_get_structure (caps, 0);
12871 gst_structure_get_int (str, "width", &width);
12874 #define UHD_SIZE 3840*2160
12876 gst_structure_get_int (str, "height", &height);
12878 if (player->v_stream_caps) {
12879 gst_caps_unref(player->v_stream_caps);
12880 player->v_stream_caps = NULL;
12883 player->v_stream_caps = gst_caps_copy(caps);
12884 debug_log ("take caps for video state tune");
12885 MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
12887 /* check video resolution */
12888 if (width*height == UHD_SIZE) {
12889 if ((util_is_miracast_connected()) && (player->msg_posted == FALSE)) {
12890 MMMessageParamType msg = {0,};
12892 msg.code = MM_ERROR_PLAYER_RESOURCE_LIMIT;
12893 debug_error("can't play in miracast");
12894 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
12895 player->msg_posted = TRUE;
12900 if ((g_strrstr(klass, "Codec/Parser/Audio")))
12902 if (player->smooth_streaming && (g_strrstr(caps_str, "audio/mpeg")))
12904 debug_log ("ssdemux can't use audio parse");
12905 result = GST_AUTOPLUG_SELECT_SKIP;
12911 if (g_strrstr(klass, "Decoder"))
12913 const char* mime = NULL;
12914 mime = gst_structure_get_name (gst_caps_get_structure(caps, 0));
12916 if (g_str_has_prefix(mime, "video"))
12918 // __mmplayer_check_video_zero_cpoy(player, factory);
12920 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
12921 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
12923 player->videodec_linked = 1;
12925 else if(g_str_has_prefix(mime, "audio"))
12927 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
12928 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
12930 player->audiodec_linked = 1;
12935 MMPLAYER_FREEIF(caps_str);
12942 static GValueArray*
12943 __mmplayer_gst_decode_autoplug_factories(GstElement *bin, GstPad* pad,
12944 GstCaps * caps, gpointer data)
12946 //mm_player_t* player = (mm_player_t*)data;
12948 debug_log("decodebin is requesting factories for caps [%s] from element[%s]",
12949 gst_caps_to_string(caps),
12950 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)));
12956 static GValueArray*
12957 __mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad* pad,
12958 GstCaps* caps, GValueArray* factories, gpointer data) // @
12960 #define DEFAULT_IDX 0xFFFF
12963 guint a_omx_idx = DEFAULT_IDX;
12964 guint a_dec_idx = DEFAULT_IDX;
12965 guint v_dec_idx = DEFAULT_IDX;
12966 guint v_parser_idx = DEFAULT_IDX;
12967 guint new_pos = DEFAULT_IDX;
12968 guint elem_idx = DEFAULT_IDX;
12970 GValueArray* new_factories = NULL;
12971 GValue val = { 0, };
12973 GstElementFactory *factory = NULL;
12974 const gchar* klass = NULL;
12975 gchar* factory_name = NULL;
12976 gchar* caps_str = NULL;
12978 mm_player_t* player = (mm_player_t*)data;
12979 caps_str = gst_caps_to_string(caps);
12981 //debug_log("autoplug-sort signal [num: %d]\n", factories->n_values);
12982 debug_log("requesting custom sorting for the factories for caps [%s]", caps_str);
12984 MMPLAYER_FREEIF(caps_str);
12986 for(idx=0; idx < factories->n_values;idx++)
12988 factory = g_value_get_object (g_value_array_get_nth (factories, idx));
12990 klass = gst_element_factory_get_klass(factory);
12991 factory_name = GST_PLUGIN_FEATURE_NAME (factory);
12993 //debug_log("Klass [%s] Factory [%s]\n", klass, factory_name);
12995 if (g_strrstr(klass, "Codec/Decoder/Audio"))
12997 if (a_dec_idx == DEFAULT_IDX)
13000 /* check ALP Codec can be used or not */
13001 if ((a_omx_idx == DEFAULT_IDX) &&
13002 (g_strrstr(factory_name, "omx_mp3dec")) &&
13003 (__mmplayer_is_omx_decoder_type(player)))
13005 debug_log("--> mp3_local : Priority of omx is higher than the others\n");
13010 else if ((v_dec_idx == DEFAULT_IDX) && (g_strrstr(klass, "Codec/Decoder/Video")))
13015 if ((v_parser_idx == DEFAULT_IDX) &&
13016 (((player->smooth_streaming) &&
13017 (g_strrstr(factory_name, "legacyh264parse"))) ||
13018 // (g_strrstr(factory_name, "h264parse")) ||
13019 (g_strrstr(factory_name, "mpeg4videoparse"))))
13021 v_parser_idx = idx;
13025 if (player->needed_v_parser || player->smooth_streaming)
13027 debug_log("needed parser? %s, ss? %s\n",
13028 (player->needed_v_parser)?"OO":"XX",
13029 (player->smooth_streaming)?"OO":"XX");
13032 new_pos = (a_dec_idx!=DEFAULT_IDX)?(a_dec_idx):((player->needed_v_parser)?(v_dec_idx):(v_parser_idx));
13033 elem_idx = (a_omx_idx!=DEFAULT_IDX)?(a_omx_idx):((player->needed_v_parser)?(v_parser_idx):(v_dec_idx));
13035 /* consider file mp3 audio only */
13036 if ((elem_idx != DEFAULT_IDX) && (new_pos < elem_idx))
13038 debug_log("[Re-arrange] factories sequence, new_pos : %d, elem_idx : %d\n", new_pos, elem_idx);
13040 new_factories = g_value_array_copy (factories);
13042 // insert omx decoder in front of other decoders
13043 factory = g_value_get_object (g_value_array_get_nth (factories, elem_idx));
13045 g_value_init (&val, G_TYPE_OBJECT);
13046 g_value_set_object (&val, factory);
13047 g_value_array_insert (new_factories, new_pos, &val);
13048 g_value_unset (&val);
13050 // remove duplicated omx element
13051 g_value_array_remove(new_factories, elem_idx+1);
13053 for(idx=0; idx < new_factories->n_values;idx++)
13055 factory = g_value_get_object (g_value_array_get_nth (new_factories, idx));
13057 debug_log("[Re-arranged] Klass [%s] Factory [%s]\n",
13058 gst_element_factory_get_klass(factory), GST_PLUGIN_FEATURE_NAME (factory));
13062 /* returning NULL to keep current order */
13063 return (new_factories)?(new_factories):(NULL);
13067 __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad* new_pad,
13068 gpointer data) // @
13070 //mm_player_t* player = (mm_player_t*)data;
13071 GstCaps* caps = NULL;
13073 debug_log("[Decodebin2] pad-removed signal\n");
13075 caps = gst_pad_get_caps(new_pad);
13078 gchar* caps_str = NULL;
13079 caps_str = gst_caps_to_string(caps);
13081 debug_log("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem) );
13083 MMPLAYER_FREEIF(caps_str);
13088 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
13090 mm_player_t* player = (mm_player_t*)data;
13093 return_if_fail ( player );
13095 debug_log("__mmplayer_gst_decode_drained");
13097 if (player->use_deinterleave == TRUE)
13099 debug_log("group playing mode.");
13103 if ( !player->cmd_lock )
13105 debug_warning("can't get cmd lock\n");
13109 if (!g_mutex_trylock(player->cmd_lock))
13111 debug_warning("Fail to get cmd lock");
13115 if (!__mmplayer_verify_next_play_path(player))
13117 debug_log("decoding is finished.");
13118 g_mutex_unlock(player->cmd_lock);
13122 player->pp_rebuilding = TRUE;
13124 /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
13125 __mmplayer_deactivate_old_path(player);
13127 g_mutex_unlock(player->cmd_lock);
13133 __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer data)
13135 mm_player_t* player = (mm_player_t*)data;
13136 const gchar* klass = NULL;
13137 gchar* factory_name = NULL;
13139 klass = gst_element_factory_get_klass (gst_element_get_factory(element));
13140 factory_name = GST_PLUGIN_FEATURE_NAME (gst_element_get_factory(element));
13142 debug_log("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
13144 if (__mmplayer_add_dump_buffer_probe(player, element))
13145 debug_log("add buffer probe");
13148 if (g_strrstr(klass, "Codec/Decoder/Audio"))
13150 gchar* selected = NULL;
13151 selected = g_strdup( GST_ELEMENT_NAME(element));
13152 player->audio_decoders = g_list_append (player->audio_decoders, selected);
13156 if (g_strrstr(klass, "Parser"))
13158 gchar* selected = NULL;
13160 selected = g_strdup (factory_name);
13161 player->parsers = g_list_append (player->parsers, selected);
13164 if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
13166 /* FIXIT : first value will be overwritten if there's more
13167 * than 1 demuxer/parser
13170 //debug_log ("plugged element is demuxer. take it\n");
13171 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
13172 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
13174 /*Added for multi audio support */ // Q. del?
13175 if (g_strrstr(klass, "Demux"))
13177 player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
13178 player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
13182 if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux"))
13184 int surface_type = 0;
13186 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
13188 /* playback protection if drm file */
13189 if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT)
13191 debug_log("playback can be protected if playready drm");
13192 g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL);
13196 // to support trust-zone only
13197 if (g_strrstr(factory_name, "asfdemux"))
13199 debug_log ("set file-location %s\n", player->profile.uri);
13200 g_object_set (G_OBJECT(element), "file-location", player->profile.uri, NULL);
13202 if (player->video_hub_download_mode == TRUE)
13204 g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
13207 else if (g_strrstr(factory_name, "legacyh264parse")) // ssdemux
13209 debug_log ("[ssdemux] output-format to legacyh264parse\n");
13210 g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
13212 else if (g_strrstr(factory_name, "mpegaudioparse"))
13214 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
13215 (__mmplayer_is_only_mp3_type(player->type)))
13217 debug_log ("[mpegaudioparse] set streaming pull mode.");
13218 g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
13221 else if (g_strrstr(factory_name, "omx_"))
13223 if (g_strrstr(klass, "Codec/Decoder/Video"))
13225 gboolean ret = FALSE;
13227 if (player->v_stream_caps != NULL)
13229 GstPad *pad = gst_element_get_static_pad(element, "sink");
13233 ret = gst_pad_set_caps(pad, player->v_stream_caps);
13234 debug_log("found omx decoder, setting gst_pad_set_caps for omx (ret:%d)", ret);
13235 MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
13236 gst_object_unref (pad);
13239 g_object_set (G_OBJECT(element), "state-tuning", TRUE, NULL);
13241 #ifdef _MM_PLAYER_ALP_PARSER
13242 if (g_strrstr(factory_name, "omx_mp3dec"))
13244 g_list_foreach (player->parsers, check_name, player);
13247 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
13250 if (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))
13252 debug_log ("plugged element is multiqueue. take it\n");
13253 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
13254 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
13256 if (MMPLAYER_IS_HTTP_STREAMING(player))
13258 __mm_player_streaming_set_multiqueue(player->streamer,
13261 MAX_DECODEBIN_BUFFER_BYTES, // player->ini.http_max_size_bytes,
13262 player->ini.http_buffering_time,
13264 player->ini.http_buffering_limit);
13266 __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
13270 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-added" );
13274 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
13277 return_val_if_fail ( player, FALSE );
13279 if ( MMPLAYER_IS_STREAMING(player) )
13282 /* This callback can be set to music player only. */
13283 if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
13285 debug_warning("audio callback is not supported for video");
13289 if (player->audio_stream_cb)
13292 GstPad *pad = NULL;
13294 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
13298 debug_error("failed to get sink pad from audiosink to probe data\n");
13302 player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
13303 G_CALLBACK (__mmplayer_audio_stream_probe), player);
13305 gst_object_unref (pad);
13312 debug_error("There is no audio callback to configure.\n");
13322 __mmplayer_init_factories(mm_player_t* player) // @
13324 return_if_fail ( player );
13326 player->factories = gst_registry_feature_filter(gst_registry_get_default(),
13327 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
13328 player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
13332 __mmplayer_release_factories(mm_player_t* player) // @
13335 return_if_fail ( player );
13337 if (player->factories)
13339 gst_plugin_feature_list_free (player->factories);
13340 player->factories = NULL;
13347 __mmplayer_release_misc(mm_player_t* player)
13350 gboolean cur_mode = player->set_mode.rich_audio;
13353 return_if_fail ( player );
13355 player->use_video_stream = FALSE;
13356 player->video_stream_cb = NULL;
13357 player->video_stream_cb_user_param = NULL;
13359 player->audio_stream_cb = NULL;
13360 player->audio_stream_cb_user_param = NULL;
13362 player->sent_bos = FALSE;
13363 player->playback_rate = DEFAULT_PLAYBACK_RATE;
13365 player->doing_seek = FALSE;
13367 player->updated_bitrate_count = 0;
13368 player->total_bitrate = 0;
13369 player->updated_maximum_bitrate_count = 0;
13370 player->total_maximum_bitrate = 0;
13372 player->not_found_demuxer = 0;
13374 player->last_position = 0;
13375 player->duration = 0;
13376 player->http_content_size = 0;
13377 player->not_supported_codec = MISSING_PLUGIN_NONE;
13378 player->can_support_codec = FOUND_PLUGIN_NONE;
13379 player->pending_seek.is_pending = FALSE;
13380 player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
13381 player->pending_seek.pos = 0;
13382 player->msg_posted = FALSE;
13383 player->has_many_types = FALSE;
13384 player->is_drm_file = FALSE;
13385 player->max_audio_channels = 0;
13386 player->video_share_api_delta = 0;
13387 player->video_share_clock_delta = 0;
13388 player->sm.keep_last_pos = FALSE;
13389 player->display_stat = MMPLAYER_DISPLAY_STATUS_NULL;
13390 player->is_subtitle_force_drop = FALSE;
13391 player->play_subtitle = FALSE;
13392 player->use_textoverlay = FALSE;
13393 player->adjust_subtitle_pos = 0;
13394 player->last_multiwin_status = FALSE;
13395 player->has_closed_caption = FALSE;
13396 player->set_mode.media_packet_video_stream = FALSE;
13398 memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
13400 player->set_mode.rich_audio = cur_mode;
13402 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
13404 player->bitrate[i] = 0;
13405 player->maximum_bitrate[i] = 0;
13408 /* free memory related to audio effect */
13409 MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
13411 if (player->state_tune_caps)
13413 gst_caps_unref(player->state_tune_caps);
13414 player->state_tune_caps = NULL;
13417 if (player->video_cb_probe_id)
13419 GstPad *pad = NULL;
13421 pad = gst_element_get_static_pad (player->video_fakesink, "sink");
13424 debug_log("release video probe\n");
13426 /* release audio callback */
13427 gst_pad_remove_buffer_probe (pad, player->video_cb_probe_id);
13428 player->video_cb_probe_id = 0;
13429 player->video_stream_cb = NULL;
13430 player->video_stream_cb_user_param = NULL;
13438 __mmplayer_release_misc_post(mm_player_t* player)
13440 char *original_uri = NULL;
13443 /* player->pipeline is already released before. */
13445 return_if_fail ( player );
13447 mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
13448 mm_attrs_set_int_by_name(player->attrs, "content_audio_found", 0);
13450 /* clean found parsers */
13451 if (player->parsers)
13453 GList *parsers = player->parsers;
13454 for ( ;parsers ; parsers = g_list_next(parsers))
13456 gchar *name = parsers->data;
13457 MMPLAYER_FREEIF(name);
13459 g_list_free(player->parsers);
13460 player->parsers = NULL;
13463 /* clean found audio decoders */
13464 if (player->audio_decoders)
13466 GList *a_dec = player->audio_decoders;
13467 for ( ;a_dec ; a_dec = g_list_next(a_dec))
13469 gchar *name = a_dec->data;
13470 MMPLAYER_FREEIF(name);
13472 g_list_free(player->audio_decoders);
13473 player->audio_decoders = NULL;
13476 /* clean the uri list except original uri */
13477 if (player->uri_info.uri_list)
13479 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
13483 mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
13484 debug_log("restore original uri = %s\n", original_uri);
13486 if (mmf_attrs_commit(player->attrs))
13488 debug_error("failed to commit the original uri.\n");
13492 GList *uri_list = player->uri_info.uri_list;
13493 for ( ;uri_list ; uri_list = g_list_next(uri_list))
13495 gchar *uri = uri_list->data;
13496 MMPLAYER_FREEIF(uri);
13498 g_list_free(player->uri_info.uri_list);
13499 player->uri_info.uri_list = NULL;
13502 player->uri_info.uri_idx = 0;
13503 player->src_changed = FALSE;
13508 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
13510 GstElement *element = NULL;
13513 debug_log("creating %s to plug\n", name);
13515 element = gst_element_factory_make(name, NULL);
13518 debug_error("failed to create queue\n");
13522 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
13524 debug_error("failed to set state READY to %s\n", name);
13525 gst_object_unref (element);
13529 if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
13531 debug_error("failed to add %s\n", name);
13532 gst_object_unref (element);
13536 sinkpad = gst_element_get_static_pad(element, "sink");
13538 if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
13540 debug_error("failed to link %s\n", name);
13541 gst_object_unref (sinkpad);
13542 gst_object_unref (element);
13546 debug_log("linked %s to pipeline successfully\n", name);
13548 gst_object_unref (sinkpad);
13554 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
13555 const char *padname, const GList *templlist)
13557 GstPad *pad = NULL;
13558 gboolean has_dynamic_pads = FALSE;
13559 gboolean has_many_types = FALSE;
13560 const char *klass = NULL;
13561 GstStaticPadTemplate *padtemplate = NULL;
13562 GstElementFactory *factory = NULL;
13563 GstElement* queue = NULL;
13564 GstElement* parser = NULL;
13565 GstPad *pssrcpad = NULL;
13566 GstPad *qsrcpad = NULL, *qsinkpad = NULL;
13567 MMPlayerGstElement *mainbin = NULL;
13568 GstStructure* str = NULL;
13569 GstCaps* srccaps = NULL;
13570 GstState target_state = GST_STATE_READY;
13571 gboolean isvideo_decoder = FALSE;
13572 guint q_max_size_time = 0;
13576 return_val_if_fail ( player &&
13577 player->pipeline &&
13578 player->pipeline->mainbin,
13581 mainbin = player->pipeline->mainbin;
13583 debug_log("plugging pad %s:%s to newly create %s:%s\n",
13584 GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
13585 GST_PAD_NAME( srcpad ),
13586 GST_ELEMENT_NAME( sinkelement ),
13589 factory = gst_element_get_factory(sinkelement);
13590 klass = gst_element_factory_get_klass(factory);
13592 /* check if player can do start continually */
13593 MMPLAYER_CHECK_CMD_IF_EXIT(player);
13595 /* need it to warm up omx before linking to pipeline */
13596 if (g_strrstr(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ), "demux"))
13598 debug_log("get demux caps.\n");
13599 if (player->state_tune_caps)
13601 gst_caps_unref(player->state_tune_caps);
13602 player->state_tune_caps = NULL;
13604 player->state_tune_caps = gst_caps_copy(GST_PAD_CAPS(srcpad));
13607 /* NOTE : OMX Codec can check if resource is available or not at this state. */
13608 if (g_strrstr(GST_ELEMENT_NAME(sinkelement), "omx"))
13610 if (player->state_tune_caps != NULL)
13612 debug_log("set demux's caps to omx codec if resource is available");
13613 if (gst_pad_set_caps(gst_element_get_static_pad(sinkelement, "sink"), player->state_tune_caps))
13615 target_state = GST_STATE_PAUSED;
13616 isvideo_decoder = TRUE;
13617 g_object_set(G_OBJECT(sinkelement), "state-tuning", TRUE, NULL);
13621 debug_warning("failed to set caps for state tuning");
13624 gst_caps_unref(player->state_tune_caps);
13625 player->state_tune_caps = NULL;
13628 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, target_state) )
13630 debug_error("failed to set %d state to %s\n", target_state, GST_ELEMENT_NAME( sinkelement ));
13631 if (isvideo_decoder)
13633 gst_element_set_state(sinkelement, GST_STATE_NULL);
13634 gst_object_unref(G_OBJECT(sinkelement));
13635 player->keep_detecting_vcodec = TRUE;
13640 /* add to pipeline */
13641 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
13643 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
13647 debug_log("element klass : %s\n", klass);
13649 /* added to support multi track files */
13650 /* only decoder case and any of the video/audio still need to link*/
13651 if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
13653 gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
13655 if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, "ssdemux"))
13657 gchar *src_demux_caps_str = NULL;
13658 gchar *needed_parser = NULL;
13659 GstCaps *src_demux_caps = NULL;
13660 gboolean smooth_streaming = FALSE;
13662 src_demux_caps = gst_pad_get_caps(srcpad);
13663 src_demux_caps_str = gst_caps_to_string(src_demux_caps);
13665 gst_caps_unref(src_demux_caps);
13667 if (g_strrstr(src_demux_caps_str, "video/x-h264"))
13669 if (g_strrstr(name, "ssdemux"))
13671 needed_parser = g_strdup("legacyh264parse");
13672 smooth_streaming = TRUE;
13676 needed_parser = g_strdup("h264parse");
13679 else if (g_strrstr(src_demux_caps_str, "video/mpeg"))
13681 needed_parser = g_strdup("mpeg4videoparse");
13683 MMPLAYER_FREEIF(src_demux_caps_str);
13687 parser = __mmplayer_element_create_and_link(player, srcpad, needed_parser);
13688 MMPLAYER_FREEIF(needed_parser);
13692 debug_error("failed to create parser\n");
13696 if (smooth_streaming)
13698 g_object_set (parser, "output-format", 1, NULL); /* NALU/Byte Stream format */
13701 /* update srcpad if parser is created */
13702 pssrcpad = gst_element_get_static_pad(parser, "src");
13707 MMPLAYER_FREEIF(name);
13709 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
13712 debug_error("failed to create queue\n");
13716 /* update srcpad to link with decoder */
13717 qsrcpad = gst_element_get_static_pad(queue, "src");
13720 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
13722 /* assigning queue handle for futher manipulation purpose */
13723 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
13724 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
13726 mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
13727 mainbin[MMPLAYER_M_Q1].gst = queue;
13729 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13731 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", 0 , NULL);
13732 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-buffers", 2, NULL);
13733 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-bytes", 0, NULL);
13737 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13738 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13741 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
13743 mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
13744 mainbin[MMPLAYER_M_Q2].gst = queue;
13746 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS)
13748 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", 0 , NULL);
13749 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-buffers", 2, NULL);
13750 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-bytes", 0, NULL);
13754 if (!MMPLAYER_IS_RTSP_STREAMING(player))
13755 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
13760 debug_error("Not supporting more then two elementary stream\n");
13764 pad = gst_element_get_static_pad(sinkelement, padname);
13768 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13769 padname, GST_ELEMENT_NAME(sinkelement) );
13771 pad = gst_element_get_static_pad(sinkelement, "sink");
13774 debug_error("failed to get pad(sink) from %s. \n",
13775 GST_ELEMENT_NAME(sinkelement) );
13780 /* to check the video/audio type set the proper flag*/
13781 const gchar *mime_type = NULL;
13783 srccaps = gst_pad_get_caps( srcpad );
13787 str = gst_caps_get_structure( srccaps, 0 );
13791 mime_type = gst_structure_get_name(str);
13796 /* link queue and decoder. so, it will be queue - decoder. */
13797 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13799 gst_object_unref(GST_OBJECT(pad));
13800 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13802 /* reconstitute supportable codec */
13803 if (strstr(mime_type, "video"))
13805 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
13807 else if (strstr(mime_type, "audio"))
13809 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
13814 if (strstr(mime_type, "video"))
13816 player->videodec_linked = 1;
13817 debug_msg("player->videodec_linked set to 1\n");
13820 else if (strstr(mime_type, "audio"))
13822 player->audiodec_linked = 1;
13823 debug_msg("player->auddiodec_linked set to 1\n");
13826 gst_object_unref(GST_OBJECT(pad));
13827 gst_caps_unref(GST_CAPS(srccaps));
13831 if ( !MMPLAYER_IS_HTTP_PD(player) )
13833 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
13835 if (MMPLAYER_IS_HTTP_STREAMING(player))
13837 GstFormat fmt = GST_FORMAT_BYTES;
13838 gint64 dur_bytes = 0L;
13839 gchar *file_buffering_path = NULL;
13840 gboolean use_file_buffer = FALSE;
13842 if ( !mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
13844 debug_log("creating http streaming buffering queue\n");
13846 queue = gst_element_factory_make("queue2", "queue2");
13849 debug_error ( "failed to create buffering queue element\n" );
13853 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
13855 debug_error("failed to set state READY to buffering queue\n");
13859 if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
13861 debug_error("failed to add buffering queue\n");
13865 qsinkpad = gst_element_get_static_pad(queue, "sink");
13866 qsrcpad = gst_element_get_static_pad(queue, "src");
13868 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
13870 debug_error("failed to link buffering queue\n");
13876 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
13877 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue;
13879 if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
13881 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
13882 debug_error("fail to get duration.\n");
13886 use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
13887 file_buffering_path = g_strdup(player->ini.http_file_buffer_path);
13895 /* NOTE : we cannot get any duration info from ts container in case of streaming */
13896 if(!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
13898 __mm_player_streaming_set_queue2(player->streamer,
13901 player->ini.http_max_size_bytes,
13902 player->ini.http_buffering_time,
13904 player->ini.http_buffering_limit,
13906 file_buffering_path,
13907 (guint64)dur_bytes);
13910 MMPLAYER_FREEIF(file_buffering_path);
13915 /* if it is not decoder or */
13916 /* in decoder case any of the video/audio still need to link*/
13917 if(!g_strrstr(klass, "Decoder"))
13920 pad = gst_element_get_static_pad(sinkelement, padname);
13923 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
13924 padname, GST_ELEMENT_NAME(sinkelement) );
13926 pad = gst_element_get_static_pad(sinkelement, "sink");
13930 debug_error("failed to get pad(sink) from %s. \n",
13931 GST_ELEMENT_NAME(sinkelement) );
13936 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
13938 gst_object_unref(GST_OBJECT(pad));
13939 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
13943 gst_object_unref(GST_OBJECT(pad));
13946 for(;templlist != NULL; templlist = templlist->next)
13948 padtemplate = templlist->data;
13950 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
13952 if( padtemplate->direction != GST_PAD_SRC ||
13953 padtemplate->presence == GST_PAD_REQUEST )
13956 switch(padtemplate->presence)
13958 case GST_PAD_ALWAYS:
13960 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
13961 GstCaps *caps = gst_pad_get_caps(srcpad);
13963 /* Check whether caps has many types */
13964 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser"))
13966 debug_log ("always pad but, caps has many types");
13967 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
13968 has_many_types = TRUE;
13972 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
13974 gst_object_unref(GST_OBJECT(srcpad));
13975 gst_caps_unref(GST_CAPS(caps));
13977 debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
13981 gst_caps_unref(GST_CAPS(caps));
13982 gst_object_unref(GST_OBJECT(srcpad));
13988 case GST_PAD_SOMETIMES:
13989 has_dynamic_pads = TRUE;
13997 /* check if player can do start continually */
13998 MMPLAYER_CHECK_CMD_IF_EXIT(player);
14000 if( has_dynamic_pads )
14002 player->have_dynamic_pad = TRUE;
14003 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
14004 G_CALLBACK(__mmplayer_add_new_pad), player);
14006 /* for streaming, more then one typefind will used for each elementary stream
14007 * so this doesn't mean the whole pipeline completion
14009 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
14011 MMPLAYER_SIGNAL_CONNECT( player, sinkelement, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
14012 G_CALLBACK(__mmplayer_pipeline_complete), player);
14016 if (has_many_types)
14018 GstPad *pad = NULL;
14020 player->has_many_types = has_many_types;
14022 pad = gst_element_get_static_pad(sinkelement, "src");
14023 MMPLAYER_SIGNAL_CONNECT (player, pad, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
14024 gst_object_unref (GST_OBJECT(pad));
14028 /* check if player can do start continually */
14029 MMPLAYER_CHECK_CMD_IF_EXIT(player);
14031 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
14033 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
14039 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
14041 debug_error("failed to set state PAUSED to queue\n");
14047 gst_object_unref (GST_OBJECT(qsrcpad));
14053 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
14055 debug_error("failed to set state PAUSED to queue\n");
14061 gst_object_unref (GST_OBJECT(pssrcpad));
14073 gst_object_unref(GST_OBJECT(qsrcpad));
14075 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
14076 * You need to explicitly set elements to the NULL state before
14077 * dropping the final reference, to allow them to clean up.
14079 gst_element_set_state(queue, GST_STATE_NULL);
14080 /* And, it still has a parent "player".
14081 * You need to let the parent manage the object instead of unreffing the object directly.
14084 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
14085 //gst_object_unref( queue );
14089 gst_caps_unref(GST_CAPS(srccaps));
14094 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
14096 const gchar *klass;
14097 //const gchar *name;
14099 /* we only care about element factories */
14100 if (!GST_IS_ELEMENT_FACTORY(feature))
14103 /* only parsers, demuxers and decoders */
14104 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
14105 //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
14107 if( g_strrstr(klass, "Demux") == NULL &&
14108 g_strrstr(klass, "Codec/Decoder") == NULL &&
14109 g_strrstr(klass, "Depayloader") == NULL &&
14110 g_strrstr(klass, "Parse") == NULL)
14118 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
14120 mm_player_t* player = (mm_player_t*) data;
14121 GstCaps *caps = NULL;
14122 GstStructure *str = NULL;
14127 return_if_fail ( pad )
14128 return_if_fail ( unused )
14129 return_if_fail ( data )
14131 caps = gst_pad_get_caps(pad);
14135 str = gst_caps_get_structure(caps, 0);
14139 name = gst_structure_get_name(str);
14142 debug_log("name=%s\n", name);
14144 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14146 debug_error("failed to autoplug for type (%s)\n", name);
14147 gst_caps_unref(caps);
14151 gst_caps_unref(caps);
14153 __mmplayer_pipeline_complete( NULL, (gpointer)player );
14160 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
14164 const char *stream_type;
14165 gchar *version_field = NULL;
14169 return_if_fail ( player );
14170 return_if_fail ( caps );
14172 str = gst_caps_get_structure(caps, 0);
14176 stream_type = gst_structure_get_name(str);
14177 if ( !stream_type )
14181 /* set unlinked mime type for downloadable codec */
14182 if (g_str_has_prefix(stream_type, "video/"))
14184 if (g_str_has_prefix(stream_type, "video/mpeg"))
14186 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14187 version_field = MM_PLAYER_MPEG_VNAME;
14189 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
14191 gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
14192 version_field = MM_PLAYER_WMV_VNAME;
14195 else if (g_str_has_prefix(stream_type, "video/x-divx"))
14197 gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
14198 version_field = MM_PLAYER_DIVX_VNAME;
14203 player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14207 player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
14210 else if (g_str_has_prefix(stream_type, "audio/"))
14212 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
14214 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
14215 version_field = MM_PLAYER_MPEG_VNAME;
14217 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
14219 gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
14220 version_field = MM_PLAYER_WMA_VNAME;
14225 player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
14229 player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
14236 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
14238 mm_player_t* player = (mm_player_t*) data;
14239 GstCaps *caps = NULL;
14240 GstStructure *str = NULL;
14244 return_if_fail ( player );
14245 return_if_fail ( pad );
14247 GST_OBJECT_LOCK (pad);
14248 if ((caps = GST_PAD_CAPS(pad)))
14249 gst_caps_ref(caps);
14250 GST_OBJECT_UNLOCK (pad);
14252 if ( NULL == caps )
14254 caps = gst_pad_get_caps(pad);
14255 if ( !caps ) return;
14258 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
14260 str = gst_caps_get_structure(caps, 0);
14264 name = gst_structure_get_name(str);
14268 player->num_dynamic_pad++;
14269 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
14271 /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
14272 * If want to play it, remove this code.
14274 if (g_strrstr(name, "application"))
14276 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
14278 /* If id3/ape tag comes, keep going */
14279 debug_log("application mime exception : id3/ape tag");
14283 /* Otherwise, we assume that this stream is subtile. */
14284 debug_log(" application mime type pad is closed.");
14288 else if (g_strrstr(name, "audio"))
14290 gint samplerate = 0, channels = 0;
14292 if (player->audiodec_linked)
14294 gst_caps_unref(caps);
14295 debug_log("multi tracks. skip to plug");
14299 /* set stream information */
14300 /* if possible, set it here because the caps is not distrubed by resampler. */
14301 gst_structure_get_int (str, "rate", &samplerate);
14302 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
14304 gst_structure_get_int (str, "channels", &channels);
14305 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
14307 debug_log("audio samplerate : %d channels : %d", samplerate, channels);
14309 else if (g_strrstr(name, "video"))
14312 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
14314 /* don't make video because of not required */
14315 if (stype == MM_DISPLAY_SURFACE_NULL)
14317 debug_log("no video because it's not required");
14321 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
14324 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
14326 debug_error("failed to autoplug for type (%s)", name);
14328 __mmplayer_set_unlinked_mime_type(player, caps);
14331 gst_caps_unref(caps);
14337 /* test API for tuning audio gain. this API should be
14338 * deprecated before the day of final release
14341 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
14343 mm_player_t* player = (mm_player_t*) hplayer;
14344 gint error = MM_ERROR_NONE;
14346 gboolean isMidi = FALSE;
14351 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14352 return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
14354 debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
14355 player->profile.play_mode, volume.level[0], volume.level[1]);
14357 isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
14364 /* is it proper volume level? */
14365 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
14367 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
14368 debug_log("Invalid Volume level!!!! \n");
14369 return MM_ERROR_INVALID_ARGUMENT;
14375 if ( player->pipeline->mainbin )
14377 GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
14379 if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
14381 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
14383 g_object_set(midi_element, "volume", volume.level[0], NULL);
14389 if ( player->pipeline->audiobin )
14391 GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
14393 /* Set to Avsysaudiosink element */
14394 if ( sink_element )
14396 gint vol_value = 0;
14397 gboolean mute = FALSE;
14398 vol_value = volume.level[0];
14400 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
14402 mute = (vol_value == 0)? TRUE:FALSE;
14404 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
14416 __mmplayer_dump_pipeline_state( mm_player_t* player )
14418 GstIterator*iter = NULL;
14419 gboolean done = FALSE;
14421 GstElement *item = NULL;
14422 GstElementFactory *factory = NULL;
14424 GstState state = GST_STATE_VOID_PENDING;
14425 GstState pending = GST_STATE_VOID_PENDING;
14426 GstClockTime time = 200*GST_MSECOND;
14430 return_val_if_fail ( player &&
14431 player->pipeline &&
14432 player->pipeline->mainbin,
14435 iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
14437 if ( iter != NULL )
14440 switch ( gst_iterator_next (iter, (gpointer)&item) )
14442 case GST_ITERATOR_OK:
14443 gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
14445 factory = gst_element_get_factory (item) ;
14448 debug_error("%s:%s : From:%s To:%s refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(item) ,
14449 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(item));
14451 gst_object_unref (item);
14453 case GST_ITERATOR_RESYNC:
14454 gst_iterator_resync (iter);
14456 case GST_ITERATOR_ERROR:
14459 case GST_ITERATOR_DONE:
14466 item = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
14468 gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
14470 factory = gst_element_get_factory (item) ;
14474 debug_error("%s:%s : From:%s To:%s refcount : %d\n",
14475 GST_OBJECT_NAME(factory),
14476 GST_ELEMENT_NAME(item),
14477 gst_element_state_get_name(state),
14478 gst_element_state_get_name(pending),
14479 GST_OBJECT_REFCOUNT_VALUE(item) );
14483 gst_iterator_free (iter);
14492 __mmplayer_check_subtitle( mm_player_t* player )
14494 MMHandleType attrs = 0;
14495 char *subtitle_uri = NULL;
14499 return_val_if_fail( player, FALSE );
14501 /* get subtitle attribute */
14502 attrs = MMPLAYER_GET_ATTRS(player);
14506 mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
14507 if ( !subtitle_uri || !strlen(subtitle_uri))
14510 debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
14511 player->is_external_subtitle_present = TRUE;
14519 __mmplayer_can_extract_pcm( mm_player_t* player )
14521 MMHandleType attrs = 0;
14522 gboolean is_drm = FALSE;
14523 gboolean sound_extraction = FALSE;
14525 return_val_if_fail ( player, FALSE );
14527 attrs = MMPLAYER_GET_ATTRS(player);
14530 debug_error("fail to get attributes.");
14534 /* check file is drm or not */
14535 if (g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm"))
14536 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
14538 /* get sound_extraction property */
14539 mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
14541 if ( ! sound_extraction || is_drm )
14543 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
14551 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
14553 MMMessageParamType msg_param;
14554 gchar *msg_src_element;
14558 return_val_if_fail( player, FALSE );
14559 return_val_if_fail( error, FALSE );
14561 /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
14563 memset (&msg_param, 0, sizeof(MMMessageParamType));
14565 if ( error->domain == GST_CORE_ERROR )
14567 msg_param.code = __gst_handle_core_error( player, error->code );
14569 else if ( error->domain == GST_LIBRARY_ERROR )
14571 msg_param.code = __gst_handle_library_error( player, error->code );
14573 else if ( error->domain == GST_RESOURCE_ERROR )
14575 msg_param.code = __gst_handle_resource_error( player, error->code );
14577 else if ( error->domain == GST_STREAM_ERROR )
14579 msg_param.code = __gst_handle_stream_error( player, error, message );
14583 debug_warning("This error domain is not defined.\n");
14585 /* we treat system error as an internal error */
14586 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
14589 if ( message->src )
14591 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14593 msg_param.data = (void *) error->message;
14595 debug_error("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
14596 msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
14600 if (msg_param.code == MM_ERROR_NONE)
14603 /* post error to application */
14604 if ( ! player->msg_posted )
14606 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14607 /* don't post more if one was sent already */
14608 player->msg_posted = TRUE;
14612 debug_log("skip error post because it's sent already.\n");
14621 __mmplayer_handle_streaming_error ( mm_player_t* player, GstMessage * message )
14624 MMMessageParamType msg_param;
14625 gchar *msg_src_element = NULL;
14626 GstStructure *s = NULL;
14627 guint error_id = 0;
14628 gchar *error_string = NULL;
14632 return_val_if_fail ( player, FALSE );
14633 return_val_if_fail ( message, FALSE );
14635 s = malloc( sizeof(GstStructure) );
14638 debug_error ("malloc fail");
14641 memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
14643 if ( !gst_structure_get_uint (s, "error_id", &error_id) )
14644 error_id = MMPLAYER_STREAMING_ERROR_NONE;
14646 switch ( error_id )
14648 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
14649 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
14651 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
14652 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
14654 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
14655 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14657 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
14658 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
14660 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
14661 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
14663 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
14664 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
14666 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
14667 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
14669 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
14670 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
14672 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
14673 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
14675 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
14676 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
14678 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
14679 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
14681 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
14682 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
14684 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
14685 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
14687 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
14688 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
14690 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
14691 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
14693 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
14694 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
14696 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
14697 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
14699 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
14700 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
14702 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
14703 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
14705 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
14706 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
14708 case MMPLAYER_STREAMING_ERROR_GONE:
14709 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
14711 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
14712 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
14714 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
14715 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
14717 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
14718 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
14720 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
14721 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
14723 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
14724 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
14726 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
14727 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
14729 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
14730 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
14732 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
14733 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
14735 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
14736 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
14738 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
14739 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
14741 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
14742 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
14744 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
14745 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
14747 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
14748 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
14750 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
14751 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
14753 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
14754 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
14756 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
14757 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
14759 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
14760 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
14762 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
14763 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
14765 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
14766 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
14768 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
14769 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
14771 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
14772 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
14774 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
14775 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
14777 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
14778 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
14780 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
14781 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
14785 MMPLAYER_FREEIF(s);
14786 return MM_ERROR_PLAYER_STREAMING_FAIL;
14790 error_string = g_strdup(gst_structure_get_string (s, "error_string"));
14791 if ( error_string )
14792 msg_param.data = (void *) error_string;
14794 if ( message->src )
14796 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
14798 debug_error("-Msg src : [%s] Code : [%x] Error : [%s] \n",
14799 msg_src_element, msg_param.code, (char*)msg_param.data );
14802 /* post error to application */
14803 if ( ! player->msg_posted )
14805 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
14807 /* don't post more if one was sent already */
14808 player->msg_posted = TRUE;
14812 debug_log("skip error post because it's sent already.\n");
14815 MMPLAYER_FREEIF(s);
14817 g_free(error_string);
14824 __gst_handle_core_error( mm_player_t* player, int code )
14826 gint trans_err = MM_ERROR_NONE;
14830 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14834 case GST_CORE_ERROR_MISSING_PLUGIN:
14835 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
14836 case GST_CORE_ERROR_STATE_CHANGE:
14837 case GST_CORE_ERROR_SEEK:
14838 case GST_CORE_ERROR_NOT_IMPLEMENTED:
14839 case GST_CORE_ERROR_FAILED:
14840 case GST_CORE_ERROR_TOO_LAZY:
14841 case GST_CORE_ERROR_PAD:
14842 case GST_CORE_ERROR_THREAD:
14843 case GST_CORE_ERROR_NEGOTIATION:
14844 case GST_CORE_ERROR_EVENT:
14845 case GST_CORE_ERROR_CAPS:
14846 case GST_CORE_ERROR_TAG:
14847 case GST_CORE_ERROR_CLOCK:
14848 case GST_CORE_ERROR_DISABLED:
14850 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
14860 __gst_handle_library_error( mm_player_t* player, int code )
14862 gint trans_err = MM_ERROR_NONE;
14866 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14870 case GST_LIBRARY_ERROR_FAILED:
14871 case GST_LIBRARY_ERROR_TOO_LAZY:
14872 case GST_LIBRARY_ERROR_INIT:
14873 case GST_LIBRARY_ERROR_SHUTDOWN:
14874 case GST_LIBRARY_ERROR_SETTINGS:
14875 case GST_LIBRARY_ERROR_ENCODE:
14877 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
14888 __gst_handle_resource_error( mm_player_t* player, int code )
14890 gint trans_err = MM_ERROR_NONE;
14894 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14898 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
14899 trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
14901 case GST_RESOURCE_ERROR_NOT_FOUND:
14902 case GST_RESOURCE_ERROR_OPEN_READ:
14903 if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
14904 || MMPLAYER_IS_RTSP_STREAMING(player))
14906 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
14909 case GST_RESOURCE_ERROR_READ:
14910 if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
14911 || MMPLAYER_IS_RTSP_STREAMING(player))
14913 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
14916 case GST_RESOURCE_ERROR_WRITE:
14917 case GST_RESOURCE_ERROR_FAILED:
14918 case GST_RESOURCE_ERROR_SEEK:
14919 case GST_RESOURCE_ERROR_TOO_LAZY:
14920 case GST_RESOURCE_ERROR_BUSY:
14921 case GST_RESOURCE_ERROR_OPEN_WRITE:
14922 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
14923 case GST_RESOURCE_ERROR_CLOSE:
14924 case GST_RESOURCE_ERROR_SYNC:
14925 case GST_RESOURCE_ERROR_SETTINGS:
14927 trans_err = MM_ERROR_PLAYER_INTERNAL;
14938 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
14940 gint trans_err = MM_ERROR_NONE;
14944 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
14945 return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
14946 return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
14948 switch ( error->code )
14950 case GST_STREAM_ERROR_FAILED:
14951 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
14952 case GST_STREAM_ERROR_DECODE:
14953 case GST_STREAM_ERROR_WRONG_TYPE:
14954 case GST_STREAM_ERROR_DECRYPT:
14955 case GST_STREAM_ERROR_DECRYPT_NOKEY:
14956 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
14957 trans_err = __gst_transform_gsterror( player, message, error );
14960 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
14961 case GST_STREAM_ERROR_TOO_LAZY:
14962 case GST_STREAM_ERROR_ENCODE:
14963 case GST_STREAM_ERROR_DEMUX:
14964 case GST_STREAM_ERROR_MUX:
14965 case GST_STREAM_ERROR_FORMAT:
14967 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
14976 /* NOTE : decide gstreamer state whether there is some playable track or not. */
14978 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
14980 gchar *src_element_name = NULL;
14981 GstElement *src_element = NULL;
14982 GstElementFactory *factory = NULL;
14983 const gchar* klass = NULL;
14988 return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
14989 return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
14990 return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
14992 src_element = GST_ELEMENT_CAST(message->src);
14993 if ( !src_element )
14994 goto INTERNAL_ERROR;
14996 src_element_name = GST_ELEMENT_NAME(src_element);
14997 if ( !src_element_name )
14998 goto INTERNAL_ERROR;
15000 factory = gst_element_get_factory(src_element);
15002 goto INTERNAL_ERROR;
15004 klass = gst_element_factory_get_klass(factory);
15006 goto INTERNAL_ERROR;
15008 debug_log("error code=%d, msg=%s, src element=%s, class=%s\n",
15009 error->code, error->message, src_element_name, klass);
15013 int msg_src_pos = 0;
15014 gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
15015 debug_log ("current active pad index -%d", active_pad_index);
15017 if (src_element_name) {
15020 if (player->audio_decoders) {
15021 GList *adec = player->audio_decoders;
15022 for ( ;adec ; adec = g_list_next(adec)) {
15023 gchar *name = adec->data;
15025 debug_log("found audio decoder name = %s", name);
15026 if (g_strrstr(name, src_element_name)) {
15033 debug_log("active pad = %d, error src index = %d", active_pad_index, msg_src_pos);
15036 if (active_pad_index != msg_src_pos) {
15037 debug_log("skip error because error is posted from no activated track");
15038 return MM_ERROR_NONE;
15043 switch ( error->code )
15045 case GST_STREAM_ERROR_DECODE:
15047 /* Demuxer can't parse one track because it's corrupted.
15048 * So, the decoder for it is not linked.
15049 * But, it has one playable track.
15051 if ( g_strrstr(klass, "Demux") )
15053 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
15055 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15057 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
15059 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15063 if ( player->pipeline->audiobin ) // PCM
15065 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15069 goto CODEC_NOT_FOUND;
15073 return MM_ERROR_PLAYER_INVALID_STREAM;
15077 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
15078 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
15079 case GST_STREAM_ERROR_WRONG_TYPE:
15080 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15082 case GST_STREAM_ERROR_FAILED:
15084 /* Decoder Custom Message */
15085 if ( strstr(error->message, "ongoing") )
15087 if ( strncasecmp(klass, "audio", 5) )
15089 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
15091 debug_log("Video can keep playing.\n");
15092 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
15096 goto CODEC_NOT_FOUND;
15100 else if ( strncasecmp(klass, "video", 5) )
15102 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
15104 debug_log("Audio can keep playing.\n");
15105 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
15109 goto CODEC_NOT_FOUND;
15113 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
15117 case GST_STREAM_ERROR_DECRYPT:
15118 case GST_STREAM_ERROR_DECRYPT_NOKEY:
15120 debug_error("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
15122 if ( strstr(error->message, "rights expired") )
15124 return MM_ERROR_PLAYER_DRM_EXPIRED;
15126 else if ( strstr(error->message, "no rights") )
15128 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
15130 else if ( strstr(error->message, "has future rights") )
15132 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
15134 else if ( strstr(error->message, "opl violation") )
15136 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
15138 return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
15148 return MM_ERROR_PLAYER_INVALID_STREAM;
15151 return MM_ERROR_PLAYER_INTERNAL;
15154 debug_log("not found any available codec. Player should be destroyed.\n");
15155 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
15159 __mmplayer_handle_eos_delay( mm_player_t* player, int delay_in_ms )
15161 return_if_fail( player );
15164 /* post now if delay is zero */
15165 if ( delay_in_ms == 0 || player->set_mode.pcm_extraction)
15167 debug_log("eos delay is zero. posting EOS now\n");
15168 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15170 if ( player->set_mode.pcm_extraction )
15171 __mmplayer_cancel_eos_timer(player);
15176 /* cancel if existing */
15177 __mmplayer_cancel_eos_timer( player );
15179 /* init new timeout */
15180 /* NOTE : consider give high priority to this timer */
15181 debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
15183 player->eos_timer = g_timeout_add( delay_in_ms,
15184 __mmplayer_eos_timer_cb, player );
15186 player->context.global_default = g_main_context_default ();
15187 debug_log("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
15189 /* check timer is valid. if not, send EOS now */
15190 if ( player->eos_timer == 0 )
15192 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
15193 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15198 __mmplayer_cancel_eos_timer( mm_player_t* player )
15200 return_if_fail( player );
15202 if ( player->eos_timer )
15204 debug_log("cancel eos timer");
15205 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
15206 player->eos_timer = 0;
15213 __mmplayer_eos_timer_cb(gpointer u_data)
15215 mm_player_t* player = NULL;
15216 player = (mm_player_t*) u_data;
15218 return_val_if_fail( player, FALSE );
15220 if ( player->play_count > 1 )
15222 gint ret_value = 0;
15223 ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
15224 if (ret_value == MM_ERROR_NONE)
15226 MMHandleType attrs = 0;
15227 attrs = MMPLAYER_GET_ATTRS(player);
15229 /* we successeded to rewind. update play count and then wait for next EOS */
15230 player->play_count--;
15232 mm_attrs_set_int_by_name(attrs, "profile_play_count", player->play_count);
15233 mmf_attrs_commit ( attrs );
15237 debug_error("seeking to 0 failed in repeat play");
15243 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
15246 /* we are returning FALSE as we need only one posting */
15250 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
15252 gint antishock = FALSE;
15253 MMHandleType attrs = 0;
15257 return_if_fail ( player && player->pipeline );
15259 /* It should be passed for video only clip */
15260 if ( ! player->pipeline->audiobin )
15263 if ( ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink")) )
15265 attrs = MMPLAYER_GET_ATTRS(player);
15268 debug_error("fail to get attributes.\n");
15272 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
15274 if (player->sm.antishock) {
15276 player->sm.antishock = 0;
15279 debug_log("setting antishock as (%d)\n", antishock);
15281 if ( disable_by_force )
15283 debug_log("but, antishock is disabled by force when is seeked\n");
15288 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
15298 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
15300 const gchar* name = NULL;
15301 GstStructure* str = NULL;
15302 GstCaps* srccaps = NULL;
15306 return_val_if_fail( player, FALSE );
15307 return_val_if_fail ( srcpad, FALSE );
15309 /* to check any of the decoder (video/audio) need to be linked to parser*/
15310 srccaps = gst_pad_get_caps( srcpad );
15314 str = gst_caps_get_structure( srccaps, 0 );
15318 name = gst_structure_get_name(str);
15322 if (strstr(name, "video"))
15324 if(player->videodec_linked)
15326 debug_msg("Video decoder already linked\n");
15330 if (strstr(name, "audio"))
15332 if(player->audiodec_linked)
15334 debug_msg("Audio decoder already linked\n");
15339 gst_caps_unref( srccaps );
15347 gst_caps_unref( srccaps );
15353 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
15355 const gchar* name = NULL;
15356 GstStructure* str = NULL;
15357 GstCaps* srccaps = NULL;
15361 return_val_if_fail ( player, FALSE );
15362 return_val_if_fail ( srcpad, FALSE );
15364 /* to check any of the decoder (video/audio) need to be linked to parser*/
15365 srccaps = gst_pad_get_caps( srcpad );
15369 str = gst_caps_get_structure( srccaps, 0 );
15373 name = gst_structure_get_name(str);
15377 if (strstr(name, "video"))
15379 if(player->videosink_linked)
15381 debug_msg("Video Sink already linked\n");
15385 if (strstr(name, "audio"))
15387 if(player->audiosink_linked)
15389 debug_msg("Audio Sink already linked\n");
15393 if (strstr(name, "text"))
15395 if(player->textsink_linked)
15397 debug_msg("Text Sink already linked\n");
15402 gst_caps_unref( srccaps );
15407 //return (!player->videosink_linked || !player->audiosink_linked);
15411 gst_caps_unref( srccaps );
15417 /* sending event to one of sinkelements */
15419 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
15421 GstEvent * event2 = NULL;
15422 GList *sinks = NULL;
15423 gboolean res = FALSE;
15424 GstPad *sinkpad = NULL;
15427 return_val_if_fail( player, FALSE );
15428 return_val_if_fail ( event, FALSE );
15430 if ( player->play_subtitle && !player->use_textoverlay)
15431 event2 = gst_event_copy((const GstEvent *)event);
15433 sinks = player->sink_elements;
15436 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
15438 if (GST_IS_ELEMENT(sink))
15440 /* keep ref to the event */
15441 gst_event_ref (event);
15443 if ( (res = gst_element_send_event (sink, event)) )
15445 debug_log("sending event[%s] to sink element [%s] success!\n",
15446 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15450 debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
15451 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
15454 sinks = g_list_next (sinks);
15459 request pad name = sink0;
15461 request pad name = sink1; // external
15464 /* Note : Textbin is not linked to the video or audio bin.
15465 * It needs to send the event to the text sink seperatelly.
15467 if ( player->play_subtitle && !player->use_textoverlay)
15469 GstElement *text_sink = NULL;
15470 gchar *change_pad_name = NULL;
15472 debug_log ("external subtitle active idx = %d", player->external_text_idx);
15474 /* To get the new pad from the selector */
15475 change_pad_name = g_strdup_printf ("sink%d", player->external_text_idx);
15476 if (change_pad_name == NULL)
15478 debug_warning ("Pad does not exists\n");
15482 g_object_get (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "active-pad", &sinkpad, NULL);
15483 if (!strcmp (GST_PAD_NAME (sinkpad), change_pad_name))
15485 debug_log ("active pad & change pad are same no need to change active pad");
15489 sinkpad = gst_element_get_static_pad (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, change_pad_name);
15490 if (sinkpad == NULL)
15492 debug_error ("failed to get static pad");;
15496 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
15497 g_object_set (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "active-pad", sinkpad, NULL);
15500 text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
15502 if (GST_IS_ELEMENT(text_sink))
15504 /* keep ref to the event */
15505 gst_event_ref (event2);
15507 if ( (res != gst_element_send_event (text_sink, event2)) )
15509 debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
15510 GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15514 debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
15515 GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) );
15518 gst_event_unref (event2);
15520 g_free(change_pad_name);
15523 gst_event_unref (event);
15531 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
15535 return_if_fail ( player );
15536 return_if_fail ( sink );
15538 player->sink_elements =
15539 g_list_append(player->sink_elements, sink);
15545 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
15549 return_if_fail ( player );
15550 return_if_fail ( sink );
15552 player->sink_elements =
15553 g_list_remove(player->sink_elements, sink);
15559 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
15560 GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
15561 gint64 cur, GstSeekType stop_type, gint64 stop )
15563 GstEvent* event = NULL;
15564 gboolean result = FALSE;
15568 return_val_if_fail( player, FALSE );
15570 __mmplayer_drop_subtitle(player, FALSE);
15572 event = gst_event_new_seek (rate, format, flags, cur_type,
15573 cur, stop_type, stop);
15575 result = __gst_send_event_to_sink( player, event );
15582 /* NOTE : be careful with calling this api. please refer to below glib comment
15583 * glib comment : Note that there is a bug in GObject that makes this function much
15584 * less useful than it might seem otherwise. Once gobject is disposed, the callback
15585 * will no longer be called, but, the signal handler is not currently disconnected.
15586 * If the instance is itself being freed at the same time than this doesn't matter,
15587 * since the signal will automatically be removed, but if instance persists,
15588 * then the signal handler will leak. You should not remove the signal yourself
15589 * because in a future versions of GObject, the handler will automatically be
15592 * It's possible to work around this problem in a way that will continue to work
15593 * with future versions of GObject by checking that the signal handler is still
15594 * connected before disconnected it:
15596 * if (g_signal_handler_is_connected (instance, id))
15597 * g_signal_handler_disconnect (instance, id);
15600 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
15602 GList* sig_list = NULL;
15603 MMPlayerSignalItem* item = NULL;
15607 return_if_fail( player );
15609 debug_log("release signals type : %d", type);
15611 if ((type < MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) || (type >= MM_PLAYER_SIGNAL_TYPE_ALL))
15613 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
15614 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
15615 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
15616 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
15617 __mmplayer_release_signal_connection (player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
15621 sig_list = player->signals[type];
15623 for ( ; sig_list; sig_list = sig_list->next )
15625 item = sig_list->data;
15627 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
15629 if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
15631 g_signal_handler_disconnect ( item->obj, item->sig );
15635 MMPLAYER_FREEIF( item );
15638 g_list_free ( player->signals[type] );
15639 player->signals[type] = NULL;
15646 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
15648 mm_player_t* player = 0;
15649 int prev_display_surface_type = 0;
15650 void *prev_display_overlay = NULL;
15651 const gchar *klass = NULL;
15652 gchar *cur_videosink_name = NULL;
15655 int num_of_dec = 2; /* DEC1, DEC2 */
15659 return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
15660 return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15662 player = MM_PLAYER_CAST(handle);
15664 if (surface_type < MM_DISPLAY_SURFACE_X && surface_type > MM_DISPLAY_SURFACE_EVAS)
15666 debug_error("Not support this surface type(%d) for changing vidoesink", surface_type);
15668 return MM_ERROR_INVALID_ARGUMENT;
15671 /* load previous attributes */
15674 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &prev_display_surface_type);
15675 mm_attrs_get_data_by_name (player->attrs, "display_overlay", &prev_display_overlay);
15676 debug_log("[0: X surface, 1: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
15677 if (prev_display_surface_type == surface_type)
15679 debug_log("incoming display surface type is same as previous one, do nothing..");
15681 return MM_ERROR_NONE;
15686 debug_error("failed to load attributes");
15688 return MM_ERROR_PLAYER_INTERNAL;
15691 /* check videosink element is created */
15692 if (!player->pipeline || !player->pipeline->videobin ||
15693 !player->pipeline->videobin[MMPLAYER_V_SINK].gst )
15695 debug_log("videosink element is not yet ready");
15697 /* videobin is not created yet, so we just set attributes related to display surface */
15698 debug_log("store display attribute for given surface type(%d)", surface_type);
15699 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
15700 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15701 if ( mmf_attrs_commit ( player->attrs ) )
15703 debug_error("failed to commit attribute");
15705 return MM_ERROR_PLAYER_INTERNAL;
15708 return MM_ERROR_NONE;
15712 /* get player command status */
15713 if ( !(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE) )
15715 debug_error("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command",player->cmd);
15717 return MM_ERROR_PLAYER_INVALID_STATE;
15720 /* get a current videosink name */
15721 cur_videosink_name = GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15723 /* surface change */
15724 for ( i = 0 ; i < num_of_dec ; i++)
15726 if ( player->pipeline->mainbin &&
15727 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst )
15729 klass = gst_element_factory_get_klass( gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) );
15730 if ((g_strrstr(klass, "Codec/Decoder/Video")))
15732 if ( !strncmp(cur_videosink_name, "x", 1) && (surface_type == MM_DISPLAY_SURFACE_EVAS) )
15734 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_evas, surface_type, display_overlay);
15741 debug_warning("success to changing display surface(%d)",surface_type);
15743 return MM_ERROR_NONE;
15746 else if (!strncmp(cur_videosink_name, "evas", 4) && (surface_type == MM_DISPLAY_SURFACE_X) )
15748 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_x, surface_type, display_overlay);
15755 debug_warning("success to changing display surface(%d)",surface_type);
15757 return MM_ERROR_NONE;
15762 debug_error("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface",surface_type, cur_videosink_name);
15763 ret = MM_ERROR_PLAYER_INTERNAL;
15772 /* rollback to previous attributes */
15773 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", prev_display_surface_type);
15774 mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(prev_display_overlay));
15775 if ( mmf_attrs_commit ( player->attrs ) )
15777 debug_error("failed to commit attributes to rollback");
15779 return MM_ERROR_PLAYER_INTERNAL;
15785 /* NOTE : It does not support some use cases, eg using colorspace converter */
15787 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
15789 GstPad *src_pad_dec = NULL;
15790 GstPad *sink_pad_videosink = NULL;
15791 GstPad *sink_pad_videobin = NULL;
15792 GstClock *clock = NULL;
15793 MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
15794 int ret = MM_ERROR_NONE;
15795 gboolean is_audiobin_created = TRUE;
15799 return_val_if_fail(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
15800 return_val_if_fail(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
15801 return_val_if_fail(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
15803 debug_log("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
15804 debug_log("surface type(%d), display overlay(%x)", surface_type, display_overlay);
15806 /* get information whether if audiobin is created */
15807 if ( !player->pipeline->audiobin ||
15808 !player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
15810 debug_warning("audiobin is null, this video content may not have audio data");
15811 is_audiobin_created = FALSE;
15814 /* get current state of player */
15815 previous_state = MMPLAYER_CURRENT_STATE(player);
15816 debug_log("previous state(%d)", previous_state);
15819 /* get src pad of decoder and block it */
15820 src_pad_dec = gst_element_get_static_pad (GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
15823 debug_error("failed to get src pad from decode in mainbin");
15824 return MM_ERROR_PLAYER_INTERNAL;
15827 if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
15829 debug_warning("trying to block pad(video)");
15830 if (!gst_pad_set_blocked (src_pad_dec, TRUE))
15832 debug_error("failed to set block pad(video)");
15833 return MM_ERROR_PLAYER_INTERNAL;
15835 debug_warning("pad is blocked(video)");
15839 /* no data flows, so no need to do pad_block */
15840 if (player->doing_seek) {
15841 debug_warning("not completed seek(%d), do nothing", player->doing_seek);
15843 debug_log("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
15847 if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
15848 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin))))
15850 debug_error("failed to remove previous ghost_pad for videobin");
15851 return MM_ERROR_PLAYER_INTERNAL;
15854 /* change state of videobin to NULL */
15855 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
15856 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
15857 if (ret != GST_STATE_CHANGE_SUCCESS)
15859 debug_error("failed to change state of videobin to NULL");
15860 return MM_ERROR_PLAYER_INTERNAL;
15863 /* unlink between decoder and videobin and remove previous videosink from videobin */
15864 GST_ELEMENT_UNLINK(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst),GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
15865 if ( !gst_bin_remove (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst)) )
15867 debug_error("failed to remove former videosink from videobin");
15868 return MM_ERROR_PLAYER_INTERNAL;
15871 __mmplayer_del_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
15873 /* create a new videosink and add it to videobin */
15874 player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, videosink_element);
15875 gst_bin_add (GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
15876 __mmplayer_add_sink( player, player->pipeline->videobin[MMPLAYER_V_SINK].gst );
15877 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
15879 /* save attributes */
15882 /* set a new display surface type */
15883 mm_attrs_set_int_by_name (player->attrs, "display_surface_type", surface_type);
15884 /* set a new diplay overlay */
15885 switch (surface_type)
15887 case MM_DISPLAY_SURFACE_X:
15888 debug_log("save attributes related to display surface to X : xid = %d", *(int*)display_overlay);
15889 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15891 case MM_DISPLAY_SURFACE_EVAS:
15892 debug_log("save attributes related to display surface to EVAS : evas image object = %x", display_overlay);
15893 mm_attrs_set_data_by_name (player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
15896 debug_error("invalid type(%d) for changing display surface",surface_type);
15898 return MM_ERROR_INVALID_ARGUMENT;
15900 if ( mmf_attrs_commit ( player->attrs ) )
15902 debug_error("failed to commit");
15904 return MM_ERROR_PLAYER_INTERNAL;
15909 debug_error("player->attrs is null, failed to save attributes");
15911 return MM_ERROR_PLAYER_INTERNAL;
15914 /* update video param */
15915 if ( MM_ERROR_NONE != _mmplayer_update_video_param( player ) )
15917 debug_error("failed to update video param");
15918 return MM_ERROR_PLAYER_INTERNAL;
15921 /* change state of videobin to READY */
15922 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
15923 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
15924 if (ret != GST_STATE_CHANGE_SUCCESS)
15926 debug_error("failed to change state of videobin to READY");
15927 return MM_ERROR_PLAYER_INTERNAL;
15930 /* change ghostpad */
15931 sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
15932 if ( !sink_pad_videosink )
15934 debug_error("failed to get sink pad from videosink element");
15935 return MM_ERROR_PLAYER_INTERNAL;
15937 player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
15938 if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE))
15940 debug_error("failed to set active to ghost_pad");
15941 return MM_ERROR_PLAYER_INTERNAL;
15943 if ( FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin) )
15945 debug_error("failed to change ghostpad for videobin");
15946 return MM_ERROR_PLAYER_INTERNAL;
15948 gst_object_unref(sink_pad_videosink);
15950 /* link decoder with videobin */
15951 sink_pad_videobin = gst_element_get_static_pad( GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
15952 if ( !sink_pad_videobin )
15954 debug_error("failed to get sink pad from videobin");
15955 return MM_ERROR_PLAYER_INTERNAL;
15957 if ( GST_PAD_LINK_OK != GST_PAD_LINK(src_pad_dec, sink_pad_videobin) )
15959 debug_error("failed to link");
15960 return MM_ERROR_PLAYER_INTERNAL;
15962 gst_object_unref(sink_pad_videobin);
15964 /* clock setting for a new videosink plugin */
15965 /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
15966 so we set it from audiosink plugin or pipeline(system clock) */
15967 if (!is_audiobin_created)
15969 debug_warning("audiobin is not created, get clock from pipeline..");
15970 clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
15974 clock = GST_ELEMENT_CLOCK (player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
15979 GstClockTime base_time;
15980 debug_log("set the clock to videosink");
15981 gst_element_set_clock (GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
15982 clock = GST_ELEMENT_CLOCK (player->pipeline->videobin[MMPLAYER_V_SINK].gst);
15985 debug_log("got clock of videosink");
15986 now = gst_clock_get_time ( clock );
15987 base_time = GST_ELEMENT_CAST (player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
15988 debug_log ("at time %" GST_TIME_FORMAT ", base %"
15989 GST_TIME_FORMAT, GST_TIME_ARGS (now), GST_TIME_ARGS (base_time));
15993 debug_error("failed to get clock of videosink after setting clock");
15994 return MM_ERROR_PLAYER_INTERNAL;
15999 debug_warning("failed to get clock, maybe it is the time before first playing");
16002 if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING)
16004 /* change state of videobin to PAUSED */
16005 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
16006 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
16007 if (ret != GST_STATE_CHANGE_FAILURE)
16009 debug_warning("change state of videobin to PLAYING, ret(%d)", ret);
16013 debug_error("failed to change state of videobin to PLAYING");
16014 return MM_ERROR_PLAYER_INTERNAL;
16017 /* release blocked and unref src pad of video decoder */
16018 if (!gst_pad_set_blocked (src_pad_dec, FALSE))
16020 debug_error("failed to set pad blocked FALSE(video)");
16021 return MM_ERROR_PLAYER_INTERNAL;
16023 debug_warning("pad is unblocked(video)");
16027 if (player->doing_seek) {
16028 debug_warning("not completed seek(%d)", player->doing_seek);
16030 /* change state of videobin to PAUSED */
16031 debug_log("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
16032 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
16033 if (ret != GST_STATE_CHANGE_FAILURE)
16035 debug_warning("change state of videobin to PAUSED, ret(%d)", ret);
16039 debug_error("failed to change state of videobin to PLAYING");
16040 return MM_ERROR_PLAYER_INTERNAL;
16043 /* already skipped pad block */
16044 debug_log("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
16047 /* do get/set position for new videosink plugin */
16049 unsigned long position = 0;
16050 gint64 pos_msec = 0;
16052 debug_log("do get/set position for new videosink plugin");
16053 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position ))
16055 debug_error("failed to get position");
16056 return MM_ERROR_PLAYER_INTERNAL;
16058 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
16059 /* accurate seek */
16060 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE ))
16062 debug_error("failed to set position");
16063 return MM_ERROR_PLAYER_INTERNAL;
16066 /* key unit seek */
16067 pos_msec = position * G_GINT64_CONSTANT(1000000);
16068 ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
16069 GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
16070 GST_SEEK_TYPE_SET, pos_msec,
16071 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
16074 debug_error("failed to set position");
16075 return MM_ERROR_PLAYER_INTERNAL;
16082 gst_object_unref (src_pad_dec);
16084 debug_log("success to change sink");
16088 return MM_ERROR_NONE;
16091 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
16093 MMPlayerGstElement* mainbin = NULL;
16094 MMPlayerGstElement* textbin = NULL;
16095 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16096 GstState current_state = GST_STATE_VOID_PENDING;
16097 GstState element_state = GST_STATE_VOID_PENDING;
16098 GstState element_pending_state = GST_STATE_VOID_PENDING;
16100 GstFormat format = GST_FORMAT_TIME;
16101 GstEvent *event = NULL;
16102 int result = MM_ERROR_NONE;
16104 GstClock *curr_clock = NULL;
16105 GstClockTime base_time, start_time, curr_time;
16110 /* check player handle */
16111 return_val_if_fail ( player && player->pipeline , MM_ERROR_PLAYER_NOT_INITIALIZED);
16113 if (!(player->pipeline->mainbin) || !(player->pipeline->textbin))
16115 debug_error("Pipeline is not in proper state\n");
16116 result = MM_ERROR_PLAYER_NOT_INITIALIZED;
16120 mainbin = player->pipeline->mainbin;
16121 textbin = player->pipeline->textbin;
16123 current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16125 // sync clock with current pipeline
16126 curr_clock = GST_ELEMENT_CLOCK (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
16127 curr_time = gst_clock_get_time (curr_clock);
16129 base_time = gst_element_get_base_time (GST_ELEMENT_CAST (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16130 start_time = gst_element_get_start_time (GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
16132 debug_log ("base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
16133 GST_TIME_ARGS (base_time), GST_TIME_ARGS (start_time), GST_TIME_ARGS (curr_time));
16135 if (current_state > GST_STATE_READY)
16137 // sync state with current pipeline
16138 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
16139 gst_element_set_state(mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, GST_STATE_PAUSED); // Naveen : enable if required only
16140 gst_element_set_state(mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst, GST_STATE_PAUSED);
16141 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
16143 ret = gst_element_get_state (mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
16144 if ( GST_STATE_CHANGE_FAILURE == ret )
16146 debug_error("fail to state change.\n");
16150 gst_element_set_base_time (textbin[MMPLAYER_T_BIN].gst, base_time);
16151 gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
16155 gst_element_set_clock (textbin[MMPLAYER_T_BIN].gst, curr_clock);
16156 gst_object_unref (curr_clock);
16159 // seek to current position
16160 if (!gst_element_query_position (mainbin[MMPLAYER_M_PIPE].gst, &format, &time))
16162 result = MM_ERROR_PLAYER_INVALID_STATE;
16163 debug_error("gst_element_query_position failed, invalid state\n");
16167 debug_log("seek time = %lld\n", time);
16169 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);
16172 __gst_send_event_to_sink(player, event);
16176 result = MM_ERROR_PLAYER_INTERNAL;
16177 debug_error("gst_event_new_seek failed\n");
16181 // sync state with current pipeline
16182 gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
16183 gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst);
16184 gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst);
16185 gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
16192 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
16194 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
16195 GstState current_state = GST_STATE_VOID_PENDING;
16197 MMHandleType attrs = 0;
16198 MMPlayerGstElement* mainbin = NULL;
16199 MMPlayerGstElement* textbin = NULL;
16201 gchar* subtitle_uri = NULL;
16202 int result = MM_ERROR_NONE;
16203 const gchar *charset = NULL;
16207 /* check player handle */
16208 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16209 return_val_if_fail( filepath, MM_ERROR_COMMON_INVALID_ARGUMENT );
16211 if (!(player->pipeline) || !(player->pipeline->mainbin))
16213 result = MM_ERROR_PLAYER_INVALID_STATE;
16214 debug_error("Pipeline is not in proper state\n");
16218 mainbin = player->pipeline->mainbin;
16219 textbin = player->pipeline->textbin;
16221 current_state = GST_STATE (mainbin[MMPLAYER_M_PIPE].gst);
16222 if (current_state < GST_STATE_READY)
16224 result = MM_ERROR_PLAYER_INVALID_STATE;
16225 debug_error("Pipeline is not in proper state\n");
16229 attrs = MMPLAYER_GET_ATTRS(player);
16232 debug_error("cannot get content attribute\n");
16233 result = MM_ERROR_PLAYER_INTERNAL;
16237 mm_attrs_get_string_by_name (attrs, "subtitle_uri", &subtitle_uri);
16238 if (!subtitle_uri || strlen(subtitle_uri) < 1)
16240 debug_error("subtitle uri is not proper filepath\n");
16241 result = MM_ERROR_PLAYER_INVALID_URI;
16245 debug_log("old subtitle file path is [%s]\n", subtitle_uri);
16246 debug_log("new subtitle file path is [%s]\n", filepath);
16248 if (!strcmp (filepath, subtitle_uri))
16250 debug_log("No need to swtich subtitle, as input filepath is same as current filepath\n");
16255 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16256 if (mmf_attrs_commit(player->attrs))
16258 debug_error("failed to commit.\n");
16263 //gst_pad_set_blocked_async(src-srcpad, TRUE)
16265 ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
16266 if (ret != GST_STATE_CHANGE_SUCCESS)
16268 debug_error("failed to change state of textbin to READY");
16269 result = MM_ERROR_PLAYER_INTERNAL;
16273 ret = gst_element_set_state(mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, GST_STATE_READY);
16274 if (ret != GST_STATE_CHANGE_SUCCESS)
16276 debug_error("failed to change state of input-selector to READY");
16277 result = MM_ERROR_PLAYER_INTERNAL;
16281 ret = gst_element_set_state(mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst, GST_STATE_READY);
16282 if (ret != GST_STATE_CHANGE_SUCCESS)
16284 debug_error("failed to change state of subparse to READY");
16285 result = MM_ERROR_PLAYER_INTERNAL;
16289 ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
16290 if (ret != GST_STATE_CHANGE_SUCCESS)
16292 debug_error("failed to change state of filesrc to READY");
16293 result = MM_ERROR_PLAYER_INTERNAL;
16297 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
16299 charset = util_get_charset(filepath);
16302 debug_log ("detected charset is %s\n", charset );
16303 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst), "subtitle-encoding", charset, NULL);
16306 result = _mmplayer_sync_subtitle_pipeline(player);
16313 /* API to switch between external subtitles */
16314 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
16316 int result = MM_ERROR_NONE;
16317 mm_player_t* player = (mm_player_t*)hplayer;
16321 /* check player handle */
16322 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16324 if (!player->pipeline) // IDLE state
16326 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16327 if (mmf_attrs_commit(player->attrs))
16329 debug_error("failed to commit.\n");
16330 result= MM_ERROR_PLAYER_INTERNAL;
16333 else // curr state <> IDLE (READY, PAUSE, PLAYING..)
16335 if ( filepath == NULL )
16336 return MM_ERROR_COMMON_INVALID_ARGUMENT;
16338 if (!__mmplayer_check_subtitle(player))
16340 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
16341 if (mmf_attrs_commit(player->attrs))
16343 debug_error("failed to commit.\n");
16344 result = MM_ERROR_PLAYER_INTERNAL;
16347 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) )
16348 debug_error("fail to create subtitle src\n");
16350 result = _mmplayer_sync_subtitle_pipeline(player);
16354 result = __mmplayer_change_external_subtitle_language(player, filepath);
16363 __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int index)
16365 int result = MM_ERROR_NONE;
16366 gchar* change_pad_name = NULL;
16367 GstPad* sinkpad = NULL;
16368 MMPlayerGstElement* mainbin = NULL;
16369 enum MainElementID elemId = MMPLAYER_M_NUM;
16370 GstCaps* caps = NULL;
16371 gint total_track_num = 0;
16375 return_val_if_fail (player && player->pipeline && player->pipeline->mainbin,
16376 MM_ERROR_PLAYER_NOT_INITIALIZED);
16378 debug_log ("Change Track(%d) to %d\n", type, index);
16380 mainbin = player->pipeline->mainbin;
16382 if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16384 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
16386 else if (type == MM_PLAYER_TRACK_TYPE_TEXT)
16388 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
16392 debug_error ("Track Type Error\n");
16396 if (mainbin[elemId].gst == NULL)
16398 result = MM_ERROR_PLAYER_NO_OP;
16399 debug_log ("Req track doesn't exist\n");
16403 total_track_num = player->selector[type].total_track_num;
16404 if (total_track_num <= 0)
16406 result = MM_ERROR_PLAYER_NO_OP;
16407 debug_log ("Language list is not available \n");
16411 if ((index < 0) || (index >= total_track_num))
16413 result = MM_ERROR_INVALID_ARGUMENT;
16414 debug_log ("Not a proper index : %d \n", index);
16418 /*To get the new pad from the selector*/
16419 change_pad_name = g_strdup_printf ("sink%d", index);
16420 if (change_pad_name == NULL)
16422 result = MM_ERROR_PLAYER_INTERNAL;
16423 debug_log ("Pad does not exists\n");
16427 debug_log ("new active pad name: %s\n", change_pad_name);
16429 sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name);
16430 if (sinkpad == NULL)
16432 result = MM_ERROR_PLAYER_INTERNAL;
16436 debug_log ("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
16437 g_object_set (mainbin[elemId].gst, "active-pad", sinkpad, NULL);
16439 caps = GST_PAD_CAPS(sinkpad);
16440 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
16443 gst_object_unref (sinkpad);
16445 if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
16447 __mmplayer_set_audio_attrs (player, caps);
16452 MMPLAYER_FREEIF(change_pad_name);
16456 int _mmplayer_change_track_language (MMHandleType hplayer, MMPlayerTrackType type, int index)
16458 int result = MM_ERROR_NONE;
16459 mm_player_t* player = NULL;
16460 MMPlayerGstElement* mainbin = NULL;
16462 gint current_active_index = 0;
16464 GstState current_state = GST_STATE_VOID_PENDING;
16465 GstEvent* event = NULL;
16466 GstFormat format = GST_FORMAT_TIME;
16471 player = (mm_player_t*)hplayer;
16472 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16474 if (!player->pipeline)
16476 debug_error ("Track %d pre setting -> %d\n", type, index);
16478 player->selector[type].active_pad_index = index;
16482 mainbin = player->pipeline->mainbin;
16484 current_active_index = player->selector[type].active_pad_index;
16486 /*If index is same as running index no need to change the pad*/
16487 if (current_active_index == index)
16492 if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, &format, &time))
16494 result = MM_ERROR_PLAYER_INVALID_STATE;
16498 current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
16499 if (current_state < GST_STATE_PAUSED)
16501 result = MM_ERROR_PLAYER_INVALID_STATE;
16502 debug_warning ("Pipeline not in porper state\n");
16506 result = __mmplayer_change_selector_pad(player, type, index);
16507 if (result != MM_ERROR_NONE)
16509 debug_error ("change selector pad error\n");
16513 player->selector[type].active_pad_index = index;
16515 if (current_state == GST_STATE_PLAYING)
16517 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);
16520 __gst_send_event_to_sink (player, event);
16524 result = MM_ERROR_PLAYER_INTERNAL;
16534 __get_state_name ( int state )
16538 case MM_PLAYER_STATE_NULL:
16540 case MM_PLAYER_STATE_READY:
16542 case MM_PLAYER_STATE_PAUSED:
16544 case MM_PLAYER_STATE_PLAYING:
16546 case MM_PLAYER_STATE_NONE:
16554 __is_rtsp_streaming ( mm_player_t* player )
16556 return_val_if_fail ( player, FALSE );
16558 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
16562 __is_wfd_streaming ( mm_player_t* player )
16564 return_val_if_fail ( player, FALSE );
16566 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
16570 __is_http_streaming ( mm_player_t* player )
16572 return_val_if_fail ( player, FALSE );
16574 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
16578 __is_streaming ( mm_player_t* player )
16580 return_val_if_fail ( player, FALSE );
16582 return ( __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
16583 || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
16587 __is_live_streaming ( mm_player_t* player )
16589 return_val_if_fail ( player, FALSE );
16591 return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
16595 __is_http_live_streaming( mm_player_t* player )
16597 return_val_if_fail( player, FALSE );
16599 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
16603 __is_dash_streaming ( mm_player_t* player )
16605 return_val_if_fail ( player, FALSE );
16607 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
16611 __is_smooth_streaming ( mm_player_t* player )
16613 return_val_if_fail ( player, FALSE );
16615 return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
16620 __is_http_progressive_down(mm_player_t* player)
16622 return_val_if_fail( player, FALSE );
16624 return ((player->pd_mode) ? TRUE:FALSE);
16628 __has_suffix(mm_player_t* player, const gchar* suffix)
16630 return_val_if_fail( player, FALSE );
16631 return_val_if_fail( suffix, FALSE );
16633 gboolean ret = FALSE;
16634 gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
16635 gchar* t_suffix = g_ascii_strdown(suffix, -1);
16637 if ( g_str_has_suffix(player->profile.uri, suffix) )
16642 MMPLAYER_FREEIF(t_url);
16643 MMPLAYER_FREEIF(t_suffix);
16649 _mmplayer_set_display_zoom(MMHandleType hplayer, float level, int x, int y)
16651 mm_player_t* player = (mm_player_t*) hplayer;
16653 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16655 MMPLAYER_VIDEO_SINK_CHECK(player);
16657 debug_log("setting display zoom level = %f, offset = %d, %d", level, x, y);
16659 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", level, "zoom-pos-x", x, "zoom-pos-y", y, NULL);
16661 return MM_ERROR_NONE;
16664 _mmplayer_get_display_zoom(MMHandleType hplayer, float *level, int *x, int *y)
16667 mm_player_t* player = (mm_player_t*) hplayer;
16668 float _level = 0.0;
16672 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16674 MMPLAYER_VIDEO_SINK_CHECK(player);
16676 g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "zoom", &_level, "zoom-pos-x", &_x, "zoom-pos-y", &_y, NULL);
16678 debug_log("display zoom level = %f, start off x = %d, y = %d", _level, _x, _y);
16684 return MM_ERROR_NONE;
16688 _mmplayer_get_video_rotate_angle(MMHandleType hplayer, int *angle)
16690 mm_player_t* player = (mm_player_t*) hplayer;
16695 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16696 return_val_if_fail ( angle, MM_ERROR_COMMON_INVALID_ARGUMENT );
16698 if (player->v_stream_caps)
16700 GstStructure *str = NULL;
16702 str = gst_caps_get_structure (player->v_stream_caps, 0);
16703 if ( !gst_structure_get_int (str, "orientation", &org_angle))
16705 debug_log ("missing 'orientation' field in video caps");
16709 debug_log("orientation: %d", org_angle);
16710 *angle = org_angle;
16713 return MM_ERROR_NONE;
16717 __mmplayer_is_streaming(mm_player_t* player)
16719 gboolean result = FALSE;
16723 return_val_if_fail (player, FALSE);
16724 result = __is_streaming (player) ;
16731 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
16733 return_val_if_fail (player, FALSE);
16734 return_val_if_fail (element, FALSE);
16736 gchar *factory_name = GST_PLUGIN_FEATURE_NAME (gst_element_get_factory(element));
16737 gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
16738 int len = PLAYER_INI_MAX_STRLEN*2;
16742 for ( idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++ )
16744 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx]))
16746 debug_log("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
16747 mm_player_dump_t *dump_s;
16748 dump_s = g_malloc (sizeof(mm_player_dump_t));
16750 if (dump_s == NULL)
16752 debug_error ("malloc fail");
16756 dump_s->dump_element_file = NULL;
16757 dump_s->dump_pad = NULL;
16758 dump_s->dump_pad = gst_element_get_static_pad (element, "sink");
16760 if (dump_s->dump_pad)
16762 memset (dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
16763 snprintf (dump_file_name, len, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
16764 dump_s->dump_element_file = fopen(dump_file_name,"w+");
16765 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);
16766 /* add list for removed buffer probe and close FILE */
16767 player->dump_list = g_list_append (player->dump_list, dump_s);
16768 debug_log ("%s sink pad added buffer probe for dump", factory_name);
16775 debug_error ("failed to get %s sink pad added", factory_name);
16785 __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstBuffer *buffer, gpointer u_data)
16787 FILE *dump_data = (FILE *) u_data;
16788 // int written = 0;
16790 return_val_if_fail ( dump_data, FALSE );
16792 // debug_log ("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS( GST_BUFFER_TIMESTAMP(buffer)));
16794 fwrite ( GST_BUFFER_DATA(buffer), 1, GST_BUFFER_SIZE(buffer), dump_data);
16800 __mmplayer_release_dump_list (GList *dump_list)
16804 GList *d_list = dump_list;
16805 for ( ;d_list ; d_list = g_list_next(d_list))
16807 mm_player_dump_t *dump_s = d_list->data;
16808 if (dump_s->dump_pad)
16810 if (dump_s->probe_handle_id)
16812 gst_pad_remove_buffer_probe (dump_s->dump_pad, dump_s->probe_handle_id);
16816 if (dump_s->dump_element_file)
16818 fclose(dump_s->dump_element_file);
16819 dump_s->dump_element_file = NULL;
16821 MMPLAYER_FREEIF(dump_s);
16823 g_list_free(dump_list);
16829 __mmplayer_ignore_current_external_display_mode(mm_player_t* player)
16831 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
16832 MMPLAYER_VIDEO_SINK_CHECK(player);
16834 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "keep-external-fullscreen-prev", TRUE, NULL);
16835 debug_log("set keep-external-fullscreen-prev property to TRUE");
16837 return MM_ERROR_NONE;
16841 _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable)
16843 mm_player_t* player = (mm_player_t*) hplayer;
16847 return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
16848 return_val_if_fail (enable == TRUE || enable == FALSE, MM_ERROR_INVALID_ARGUMENT);
16850 player->set_mode.media_packet_video_stream = enable;
16854 return MM_ERROR_NONE;