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>, YoungHwan An <younghwan_.an@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 /*===========================================================================================
26 ========================================================================================== */
29 #include <gst/app/gstappsrc.h>
30 #ifndef GST_API_VERSION_1
31 #include <gst/interfaces/xoverlay.h>
33 #include <gst/video/videooverlay.h>
43 #include <mm_attrs_private.h>
46 #include "mm_player_priv.h"
47 #include "mm_player_ini.h"
48 #include "mm_player_attrs.h"
49 #include "mm_player_capture.h"
50 #include "mm_player_priv_internal.h"
51 #include "mm_player_priv_locl_func.h"
53 /*===========================================================================================
55 | LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
57 ========================================================================================== */
59 /*---------------------------------------------------------------------------
60 | GLOBAL CONSTANT DEFINITIONS: |
61 ---------------------------------------------------------------------------*/
63 /*---------------------------------------------------------------------------
64 | IMPORTED VARIABLE DECLARATIONS: |
65 ---------------------------------------------------------------------------*/
67 /*---------------------------------------------------------------------------
68 | IMPORTED FUNCTION DECLARATIONS: |
69 ---------------------------------------------------------------------------*/
71 /*---------------------------------------------------------------------------
73 ---------------------------------------------------------------------------*/
74 #define TRICK_PLAY_MUTE_THRESHOLD_MAX 2.0
75 #define TRICK_PLAY_MUTE_THRESHOLD_MIN 0.0
77 #define MM_VOLUME_FACTOR_DEFAULT 1.0
78 #define MM_VOLUME_FACTOR_MIN 0
79 #define MM_VOLUME_FACTOR_MAX 1.0
81 #define MM_PLAYER_MPEG_VNAME "mpegversion"
82 #define MM_PLAYER_DIVX_VNAME "divxversion"
83 #define MM_PLAYER_WMV_VNAME "wmvversion"
84 #define MM_PLAYER_WMA_VNAME "wmaversion"
86 #define DEFAULT_PLAYBACK_RATE 1.0
88 #define GST_QUEUE_DEFAULT_TIME 8
89 #define GST_QUEUE_HLS_TIME 8
91 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && (PLAYER_INI()->http_file_buffer_path) && (strlen(PLAYER_INI()->http_file_buffer_path) > 0) )
93 #define LAZY_PAUSE_TIMEOUT_MSEC 700
95 /*---------------------------------------------------------------------------
96 | LOCAL CONSTANT DEFINITIONS: |
97 ---------------------------------------------------------------------------*/
99 /*---------------------------------------------------------------------------
100 | LOCAL DATA TYPE DEFINITIONS: |
101 ---------------------------------------------------------------------------*/
103 /*---------------------------------------------------------------------------
104 | GLOBAL VARIABLE DEFINITIONS: |
105 ---------------------------------------------------------------------------*/
107 /*---------------------------------------------------------------------------
108 | LOCAL VARIABLE DEFINITIONS: |
109 ---------------------------------------------------------------------------*/
111 /*---------------------------------------------------------------------------
112 | LOCAL FUNCTION PROTOTYPES: |
113 ---------------------------------------------------------------------------*/
114 static int __mmplayer_get_state(mm_player_t* player);
115 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
116 static gboolean __mmplayer_is_amr_type (gchar *str_caps);
117 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
119 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
120 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
121 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
123 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
124 static void __mmplayer_init_factories(mm_player_t* player);
125 static void __mmplayer_release_factories(mm_player_t* player);
126 static gboolean __mmplayer_gstreamer_init(void);
128 gboolean __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param);
130 int __mmplayer_switch_audio_sink (mm_player_t* player);
131 static int __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
132 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
133 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
134 static int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime);
135 static gpointer __mmplayer_repeat_thread(gpointer data);
136 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
137 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
140 const gchar * __get_state_name ( int state );
142 static gboolean __mmplayer_warm_up_video_codec( mm_player_t* player, GstElementFactory *factory);
144 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
145 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
146 static int __mmplayer_start_streaming_ext(mm_player_t *player);
147 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
150 /*===========================================================================================
152 | FUNCTION DEFINITIONS |
154 ========================================================================================== */
156 /* implementing player FSM */
157 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
159 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
161 MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
162 MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
163 MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
164 MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
168 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
170 //debug_log("incomming command : %d \n", command );
172 current_state = MMPLAYER_CURRENT_STATE(player);
173 pending_state = MMPLAYER_PENDING_STATE(player);
174 target_state = MMPLAYER_TARGET_STATE(player);
175 prev_state = MMPLAYER_PREV_STATE(player);
177 MMPLAYER_PRINT_STATE(player);
181 case MMPLAYER_COMMAND_CREATE:
183 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
185 if ( current_state == MM_PLAYER_STATE_NULL ||
186 current_state == MM_PLAYER_STATE_READY ||
187 current_state == MM_PLAYER_STATE_PAUSED ||
188 current_state == MM_PLAYER_STATE_PLAYING )
193 case MMPLAYER_COMMAND_DESTROY:
195 /* destroy can called anytime */
197 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
201 case MMPLAYER_COMMAND_REALIZE:
203 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
205 if ( pending_state != MM_PLAYER_STATE_NONE )
211 /* need ready state to realize */
212 if ( current_state == MM_PLAYER_STATE_READY )
215 if ( current_state != MM_PLAYER_STATE_NULL )
221 case MMPLAYER_COMMAND_UNREALIZE:
223 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
225 if ( current_state == MM_PLAYER_STATE_NULL )
230 case MMPLAYER_COMMAND_START:
232 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
234 if ( pending_state == MM_PLAYER_STATE_NONE )
236 if ( current_state == MM_PLAYER_STATE_PLAYING )
238 else if ( current_state != MM_PLAYER_STATE_READY &&
239 current_state != MM_PLAYER_STATE_PAUSED )
242 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
246 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
248 debug_log("player is going to paused state, just change the pending state as playing");
257 case MMPLAYER_COMMAND_STOP:
259 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
261 if ( current_state == MM_PLAYER_STATE_READY )
264 /* need playing/paused state to stop */
265 if ( current_state != MM_PLAYER_STATE_PLAYING &&
266 current_state != MM_PLAYER_STATE_PAUSED )
271 case MMPLAYER_COMMAND_PAUSE:
273 if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
276 if (player->doing_seek)
277 goto NOT_COMPLETED_SEEK;
279 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
281 if ( pending_state == MM_PLAYER_STATE_NONE )
283 if ( current_state == MM_PLAYER_STATE_PAUSED )
285 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
288 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
292 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
294 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
295 debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
303 case MMPLAYER_COMMAND_RESUME:
305 if ( MMPLAYER_IS_LIVE_STREAMING(player) )
308 if (player->doing_seek)
309 goto NOT_COMPLETED_SEEK;
311 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
313 if ( pending_state == MM_PLAYER_STATE_NONE )
315 if ( current_state == MM_PLAYER_STATE_PLAYING )
317 else if ( current_state != MM_PLAYER_STATE_PAUSED )
320 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
324 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
326 debug_log("player is going to paused state, just change the pending state as playing");
338 player->cmd = command;
341 return MM_ERROR_NONE;
344 debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
345 MMPLAYER_STATE_GET_NAME(current_state), command);
346 return MM_ERROR_PLAYER_INVALID_STATE;
349 debug_warning("not completed seek");
350 return MM_ERROR_PLAYER_DOING_SEEK;
353 debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
354 return MM_ERROR_PLAYER_NO_OP;
357 debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
358 return MM_ERROR_PLAYER_NO_OP;
362 __mmplayer_videostream_cb(GstElement *element, void *stream,
363 int width, int height, gpointer data) // @
365 mm_player_t* player = (mm_player_t*)data;
368 return_if_fail ( player );
372 if (player->video_stream_cb )
374 length = width * height * 4; // for rgb 32bit
375 player->video_stream_cb(stream, length, player->video_stream_cb_user_param, width, height);
382 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
384 mm_player_t* player = (mm_player_t*)data;
386 return_if_fail ( player );
390 if (player->video_frame_render_error_cb )
394 int surface_type = 0;
395 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
396 switch (surface_type)
398 case MM_DISPLAY_SURFACE_X_EXT:
399 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
400 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
403 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
409 debug_error("could not get surface type");
414 debug_warning("video_frame_render_error_cb was not set");
420 /* This function should be called after the pipeline goes PAUSED or higher
423 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
425 static gboolean has_duration = FALSE;
426 static gboolean has_video_attrs = FALSE;
427 static gboolean has_audio_attrs = FALSE;
428 static gboolean has_bitrate = FALSE;
429 gboolean missing_only = FALSE;
430 gboolean all = FALSE;
432 #ifndef GST_API_VERSION_1
433 GstFormat fmt = GST_FORMAT_TIME;
436 GstStructure* p = NULL;
437 MMHandleType attrs = 0;
439 gint stream_service_type = STREAMING_SERVICE_NONE;
444 return_val_if_fail ( player, FALSE );
446 /* check player state here */
447 if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
448 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
450 /* give warning now only */
451 debug_warning("be careful. content attributes may not available in this state ");
454 /* get content attribute first */
455 attrs = MMPLAYER_GET_ATTRS(player);
458 debug_error("cannot get content attribute");
462 /* get update flag */
464 if ( flag & ATTR_MISSING_ONLY )
467 debug_log("updating missed attr only");
470 if ( flag & ATTR_ALL )
473 has_duration = FALSE;
474 has_video_attrs = FALSE;
475 has_audio_attrs = FALSE;
478 debug_log("updating all attrs");
481 if ( missing_only && all )
483 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
484 missing_only = FALSE;
487 if ( (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
489 debug_log("try to update duration");
490 has_duration = FALSE;
492 #ifdef GST_API_VERSION_1
493 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
495 player->duration = dur_nsec;
496 debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
499 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
501 player->duration = dur_nsec;
502 debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
506 /* try to get streaming service type */
507 stream_service_type = __mmplayer_get_stream_service_type( player );
508 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
510 /* check duration is OK */
511 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
513 debug_error("not ready to get duration");
518 mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
520 debug_log("duration updated");
524 if ( (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
526 /* update audio params
527 NOTE : We need original audio params and it can be only obtained from src pad of audio
528 decoder. Below code only valid when we are not using 'resampler' just before
531 debug_log("try to update audio attrs");
532 has_audio_attrs = FALSE;
534 if ( player->pipeline->audiobin &&
535 player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
537 GstCaps *caps_a = NULL;
539 gint samplerate = 0, channels = 0;
541 pad = gst_element_get_static_pad(
542 player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
546 #ifdef GST_API_VERSION_1
547 caps_a = gst_pad_get_current_caps( pad );
549 caps_a = gst_pad_get_negotiated_caps( pad );
554 p = gst_caps_get_structure (caps_a, 0);
556 mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
558 gst_structure_get_int (p, "rate", &samplerate);
559 mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
561 gst_structure_get_int (p, "channels", &channels);
562 mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
564 debug_log("samplerate : %d channels : %d", samplerate, channels);
566 gst_caps_unref( caps_a );
569 has_audio_attrs = TRUE;
573 debug_warning("not ready to get audio caps");
576 gst_object_unref( pad );
580 debug_warning("failed to get pad from audiosink");
585 if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
587 debug_log("try to update video attrs");
588 has_video_attrs = FALSE;
590 if ( player->pipeline->videobin &&
591 player->pipeline->videobin[MMPLAYER_V_SINK].gst )
593 GstCaps *caps_v = NULL;
598 pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
601 #ifdef GST_API_VERSION_1
602 caps_v = gst_pad_get_current_caps( pad );
604 caps_v = gst_pad_get_negotiated_caps( pad );
608 p = gst_caps_get_structure (caps_v, 0);
609 gst_structure_get_int (p, "width", &width);
610 mm_attrs_set_int_by_name(attrs, "content_video_width", width);
612 gst_structure_get_int (p, "height", &height);
613 mm_attrs_set_int_by_name(attrs, "content_video_height", height);
615 gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
617 debug_log("width : %d height : %d", width, height );
619 gst_caps_unref( caps_v );
624 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
625 debug_log("fps : %d", tmpNu / tmpDe);
628 has_video_attrs = TRUE;
632 debug_log("no negitiated caps from videosink");
634 gst_object_unref( pad );
639 debug_log("no videosink sink pad");
645 if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
647 debug_log("try to update bitrate");
650 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
651 if (player->duration)
653 guint64 data_size = 0;
655 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
657 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
659 if (stat(path, &sb) == 0)
661 data_size = (guint64)sb.st_size;
664 else if (MMPLAYER_IS_HTTP_STREAMING(player))
666 data_size = player->http_content_size;
672 guint64 msec_dur = 0;
674 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
675 bitrate = data_size * 8 * 1000 / msec_dur;
676 debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
677 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
685 if ( mmf_attrs_commit ( attrs ) )
687 debug_error("failed to update attributes\n");
695 static gint __mmplayer_get_stream_service_type( mm_player_t* player )
697 gint streaming_type = STREAMING_SERVICE_NONE;
701 return_val_if_fail ( player &&
703 player->pipeline->mainbin &&
704 player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
707 /* streaming service type if streaming */
708 if ( ! MMPLAYER_IS_STREAMING(player) )
710 debug_log("not a streamming");
711 return STREAMING_SERVICE_NONE;
714 if (MMPLAYER_IS_RTSP_STREAMING(player))
716 /* get property from rtspsrc element */
717 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst),
718 "service_type", &streaming_type, NULL);
720 else if (MMPLAYER_IS_HTTP_STREAMING(player))
722 streaming_type = player->duration == 0 ?
723 STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
726 switch ( streaming_type )
728 case STREAMING_SERVICE_LIVE:
729 debug_log("it's live streaming");
731 case STREAMING_SERVICE_VOD:
732 debug_log("it's vod streaming");
734 case STREAMING_SERVICE_NONE:
735 debug_error("should not get here");
738 debug_error("should not get here");
741 player->streaming_type = streaming_type;
744 return streaming_type;
748 /* this function sets the player state and also report
749 * it to applicaton by calling callback function
752 __mmplayer_set_state(mm_player_t* player, int state) // @
754 MMMessageParamType msg = {0, };
755 int asm_result = MM_ERROR_NONE;
756 gboolean post_bos = FALSE;
757 gboolean interrupted_by_asm = FALSE;
760 return_val_if_fail ( player, FALSE );
762 if ( MMPLAYER_CURRENT_STATE(player) == state )
764 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
765 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
769 /* update player states */
770 MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
771 MMPLAYER_CURRENT_STATE(player) = state;
773 /* FIXIT : it's better to do like below code
774 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
775 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
776 and add more code to handling PENDING_STATE.
778 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
779 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
782 MMPLAYER_PRINT_STATE(player);
784 /* do some FSM stuffs before posting new state to application */
785 interrupted_by_asm = player->sm.by_asm_cb;
787 switch ( MMPLAYER_CURRENT_STATE(player) )
789 case MM_PLAYER_STATE_NULL:
790 case MM_PLAYER_STATE_READY:
792 if (player->cmd == MMPLAYER_COMMAND_STOP)
794 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP);
795 if ( asm_result != MM_ERROR_NONE )
797 debug_error("failed to set asm state to stop\n");
804 case MM_PLAYER_STATE_PAUSED:
806 if ( ! player->sent_bos )
808 /* it's first time to update all content attrs. */
809 _mmplayer_update_content_attrs( player, ATTR_ALL );
812 /* add audio callback probe if condition is satisfied */
813 if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
815 __mmplayer_configure_audio_callback(player);
818 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE);
821 debug_error("failed to set asm state to PAUSE\n");
827 case MM_PLAYER_STATE_PLAYING:
829 /* try to get content metadata */
830 if ( ! player->sent_bos )
832 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
833 * c-api since c-api doesn't use _start() anymore. It may not work propery with
834 * legacy mmfw-player api */
835 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
838 if ( player->cmd == MMPLAYER_COMMAND_START && !player->sent_bos )
840 __mmplayer_handle_missed_plugin ( player );
842 /* update video resource status */
843 if ( ( player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO )
845 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING);
848 MMMessageParamType msg = {0, };
850 debug_error("failed to go ahead because of video conflict\n");
852 msg.union_type = MM_MSG_UNION_CODE;
853 msg.code = MM_ERROR_POLICY_INTERRUPTED;
854 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
856 _mmplayer_unrealize((MMHandleType)player);
863 if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
865 /* initialize because auto resume is done well. */
866 player->resumed_by_rewind = FALSE;
867 player->playback_rate = 1.0;
870 if ( !player->sent_bos )
872 /* check audio codec field is set or not
873 * we can get it from typefinder or codec's caps.
875 gchar *audio_codec = NULL;
876 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
878 /* The codec format can't be sent for audio only case like amr, mid etc.
879 * Because, parser don't make related TAG.
880 * So, if it's not set yet, fill it with found data.
884 if ( g_strrstr(player->type, "audio/midi"))
886 audio_codec = g_strdup("MIDI");
889 else if ( g_strrstr(player->type, "audio/x-amr"))
891 audio_codec = g_strdup("AMR");
893 else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
895 audio_codec = g_strdup("AAC");
899 audio_codec = g_strdup("unknown");
901 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
903 MMPLAYER_FREEIF(audio_codec);
904 mmf_attrs_commit(player->attrs);
905 debug_log("set audio codec type with caps\n");
913 case MM_PLAYER_STATE_NONE:
915 debug_warning("invalid target state, there is nothing to do.\n");
920 /* post message to application */
921 if (MMPLAYER_TARGET_STATE(player) == state)
923 /* fill the message with state of player */
924 msg.state.previous = MMPLAYER_PREV_STATE(player);
925 msg.state.current = MMPLAYER_CURRENT_STATE(player);
927 /* state changed by asm callback */
928 if ( interrupted_by_asm )
930 msg.union_type = MM_MSG_UNION_CODE;
931 msg.code = player->sm.event_src;
932 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
934 /* state changed by usecase */
937 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
940 debug_log ("player reach the target state, then do something in each state(%s).\n",
941 MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
945 debug_log ("intermediate state, do nothing.\n");
946 MMPLAYER_PRINT_STATE(player);
952 MMTA_ACUM_ITEM_END("[KPI] start media player service", FALSE);
953 MMTA_ACUM_ITEM_END("[KPI] media player service create->playing", FALSE);
955 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
956 player->sent_bos = TRUE;
965 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
967 return_val_if_fail( player, FALSE );
971 if ( !player->msg_cb )
973 debug_warning("no msg callback. can't post msg now\n");
977 //debug_log("Message (type : %d) will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
979 player->msg_cb(msgtype, param, player->msg_cb_param);
988 __mmplayer_get_state(mm_player_t* player) // @
990 int state = MM_PLAYER_STATE_NONE;
994 return_val_if_fail ( player, MM_PLAYER_STATE_NONE );
996 state = MMPLAYER_CURRENT_STATE(player);
998 debug_log("player state is %s.\n", MMPLAYER_STATE_GET_NAME(state));
1006 __gst_set_async_state_change(mm_player_t* player, gboolean async)
1009 return_if_fail( player && player->pipeline && player->pipeline->mainbin );
1011 /* need only when we are using decodebin */
1012 if ( ! PLAYER_INI()->use_decodebin )
1016 if ( player->pipeline->audiobin &&
1017 player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1019 debug_log("audiosink async : %d\n", async);
1020 g_object_set (G_OBJECT (player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "async", async, NULL);
1024 if ( player->pipeline->videobin &&
1025 player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1027 debug_log("videosink async : %d\n", async);
1028 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "async", async, NULL);
1031 /* decodebin if enabled */
1032 if ( PLAYER_INI()->use_decodebin )
1034 debug_log("decodebin async : %d\n", async);
1035 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst), "async-handling", async, NULL);
1041 static gpointer __mmplayer_repeat_thread(gpointer data)
1043 mm_player_t* player = (mm_player_t*) data;
1044 gboolean ret_value = FALSE;
1045 MMHandleType attrs = 0;
1048 return_val_if_fail ( player, NULL );
1050 while ( ! player->repeat_thread_exit )
1052 debug_log("repeat thread started. waiting for signal.\n");
1053 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1055 if ( player->repeat_thread_exit )
1057 debug_log("exiting repeat thread\n");
1061 if ( !player->cmd_lock )
1063 debug_log("can't get cmd lock\n");
1068 g_mutex_lock(player->cmd_lock);
1070 attrs = MMPLAYER_GET_ATTRS(player);
1072 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1074 debug_error("can not get play count\n");
1078 if ( player->section_repeat )
1080 ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1084 if ( player->playback_rate < 0.0 )
1086 player->resumed_by_rewind = TRUE;
1087 _mmplayer_set_mute((MMHandleType)player, 0);
1088 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1091 ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1092 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1093 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1096 player->sent_bos = FALSE;
1101 debug_error("failed to set position to zero for rewind\n");
1105 /* decrease play count */
1108 /* we successeded to rewind. update play count and then wait for next EOS */
1111 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1113 /* commit attribute */
1114 if ( mmf_attrs_commit ( attrs ) )
1116 debug_error("failed to commit attribute\n");
1121 g_mutex_unlock(player->cmd_lock);
1128 __mmplayer_handle_buffering_message ( mm_player_t* player )
1130 MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1131 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1132 MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1133 MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1135 return_if_fail ( player );
1137 prev_state = MMPLAYER_PREV_STATE(player),
1138 current_state = MMPLAYER_CURRENT_STATE(player);
1139 target_state = MMPLAYER_TARGET_STATE(player);
1140 pending_state = MMPLAYER_PENDING_STATE(player);
1142 if ( MMPLAYER_IS_RTSP_STREAMING(player) )
1145 if ( !player->streamer->is_buffering )
1147 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1148 MMPLAYER_STATE_GET_NAME(prev_state),
1149 MMPLAYER_STATE_GET_NAME(current_state),
1150 MMPLAYER_STATE_GET_NAME(pending_state),
1151 MMPLAYER_STATE_GET_NAME(target_state));
1153 /* NOTE : if buffering has done, player has to go to target state. */
1154 switch ( target_state )
1156 case MM_PLAYER_STATE_PAUSED :
1158 switch ( pending_state )
1160 case MM_PLAYER_STATE_PLAYING:
1162 __gst_pause ( player, TRUE );
1166 case MM_PLAYER_STATE_PAUSED:
1168 debug_log("player is already going to paused state, there is nothing to do.\n");
1172 case MM_PLAYER_STATE_NONE:
1173 case MM_PLAYER_STATE_NULL:
1174 case MM_PLAYER_STATE_READY:
1177 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1184 case MM_PLAYER_STATE_PLAYING :
1186 switch ( pending_state )
1188 case MM_PLAYER_STATE_NONE:
1190 if (current_state != MM_PLAYER_STATE_PLAYING)
1191 __gst_resume ( player, TRUE );
1195 case MM_PLAYER_STATE_PAUSED:
1197 /* NOTE: It should be worked as asynchronously.
1198 * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1200 __gst_resume ( player, TRUE );
1204 case MM_PLAYER_STATE_PLAYING:
1206 debug_log("player is already going to playing state, there is nothing to do.\n");
1210 case MM_PLAYER_STATE_NULL:
1211 case MM_PLAYER_STATE_READY:
1214 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1221 case MM_PLAYER_STATE_NULL :
1222 case MM_PLAYER_STATE_READY :
1223 case MM_PLAYER_STATE_NONE :
1226 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1233 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1234 * it's for stopping the pipeline clock to prevent dropping the data in sink element.
1236 switch ( pending_state )
1238 case MM_PLAYER_STATE_NONE:
1240 if (current_state != MM_PLAYER_STATE_PAUSED)
1241 __gst_pause ( player, TRUE );
1245 case MM_PLAYER_STATE_PLAYING:
1247 __gst_pause ( player, TRUE );
1251 case MM_PLAYER_STATE_PAUSED:
1253 debug_log("player is already going to paused state, there is nothing to do.\n");
1257 case MM_PLAYER_STATE_NULL:
1258 case MM_PLAYER_STATE_READY:
1261 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1270 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
1272 int pro_value = 0; // in the case of expection, default will be returned.
1273 int dest_angle = rotation_angle;
1274 int rotation_using_type = -1;
1275 #define ROTATION_USING_X 0
1276 #define ROTATION_USING_FIMC 1
1277 #define ROTATION_USING_FLIP 2
1279 return_val_if_fail(player, FALSE);
1280 return_val_if_fail(value, FALSE);
1281 return_val_if_fail(rotation_angle >= 0, FALSE);
1283 if (rotation_angle >= 360)
1285 dest_angle = rotation_angle - 360;
1288 /* chech if supported or not */
1289 if ( dest_angle % 90 )
1291 debug_log("not supported rotation angle = %d", rotation_angle);
1295 if (player->use_video_stream)
1297 if (player->is_nv12_tiled)
1299 rotation_using_type = ROTATION_USING_FIMC;
1303 rotation_using_type = ROTATION_USING_FLIP;
1308 int surface_type = 0;
1309 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
1310 debug_log("check display surface type for rotation: %d", surface_type);
1312 switch (surface_type)
1314 case MM_DISPLAY_SURFACE_X:
1315 rotation_using_type = ROTATION_USING_X;
1317 case MM_DISPLAY_SURFACE_EVAS:
1318 if (player->is_nv12_tiled && !strcmp(PLAYER_INI()->videosink_element_evas,"evasimagesink"))
1320 rotation_using_type = ROTATION_USING_FIMC;
1322 else if (!player->is_nv12_tiled)
1324 rotation_using_type = ROTATION_USING_FLIP;
1328 debug_error("it should not be here..");
1333 rotation_using_type = ROTATION_USING_FLIP;
1338 debug_log("using %d type for rotation", rotation_using_type);
1340 /* get property value for setting */
1341 switch(rotation_using_type)
1343 case ROTATION_USING_X: // xvimagesink
1350 pro_value = 3; // clockwise 90
1356 pro_value = 1; // counter-clockwise 90
1361 case ROTATION_USING_FIMC: // fimcconvert
1368 pro_value = 90; // clockwise 90
1374 pro_value = 270; // counter-clockwise 90
1379 case ROTATION_USING_FLIP: // videoflip
1387 pro_value = 1; // clockwise 90
1393 pro_value = 3; // counter-clockwise 90
1400 debug_log("setting rotation property value : %d", pro_value);
1408 _mmplayer_update_video_param(mm_player_t* player) // @
1410 MMHandleType attrs = 0;
1411 int surface_type = 0;
1412 int org_angle = 0; // current supported angle values are 0, 90, 180, 270
1414 int user_angle_type= 0;
1415 int rotation_value = 0;
1419 /* check video sinkbin is created */
1420 return_val_if_fail ( player &&
1422 player->pipeline->videobin &&
1423 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
1424 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1425 MM_ERROR_PLAYER_NOT_INITIALIZED );
1427 attrs = MMPLAYER_GET_ATTRS(player);
1430 debug_error("cannot get content attribute");
1431 return MM_ERROR_PLAYER_INTERNAL;
1434 /* update user roation */
1435 mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
1437 /* get angle with user type */
1438 switch(user_angle_type)
1440 case MM_DISPLAY_ROTATION_NONE:
1443 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
1446 case MM_DISPLAY_ROTATION_180:
1449 case MM_DISPLAY_ROTATION_270: // clockwise 90
1454 /* get original orientation */
1455 if (player->v_stream_caps)
1457 GstStructure *str = NULL;
1459 str = gst_caps_get_structure (player->v_stream_caps, 0);
1460 if ( !gst_structure_get_int (str, "orientation", &org_angle))
1462 debug_log ("missing 'orientation' field in video caps");
1466 debug_log("origianl video orientation = %d", org_angle);
1470 debug_log("check user angle: %d, org angle: %d", user_angle, org_angle);
1472 /* get rotation value to set */
1473 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1475 /* check video stream callback is used */
1476 if( player->use_video_stream )
1478 if (player->is_nv12_tiled)
1480 gchar *ename = NULL;
1484 mm_attrs_get_int_by_name(attrs, "display_width", &width);
1485 mm_attrs_get_int_by_name(attrs, "display_height", &height);
1487 /* resize video frame with requested values for fimcconvert */
1488 #ifdef GST_API_VERSION_1
1489 ename = GST_OBJECT (gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1491 ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1494 if (g_strrstr(ename, "fimcconvert"))
1497 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1500 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1502 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
1503 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
1507 debug_error("no available video converter");
1508 return MM_ERROR_PLAYER_INTERNAL;
1513 debug_log("using video stream callback with memsink. player handle : [%p]", player);
1515 g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1518 return MM_ERROR_NONE;
1521 /* update display surface */
1522 mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
1523 debug_log("check display surface type attribute: %d", surface_type);
1525 /* configuring display */
1526 switch ( surface_type )
1528 case MM_DISPLAY_SURFACE_X:
1530 /* ximagesink or xvimagesink */
1533 int display_method = 0;
1538 int force_aspect_ratio = 0;
1539 gboolean visible = TRUE;
1541 /* common case if using x surface */
1542 mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
1545 #define GST_VAAPI_DISPLAY_TYPE_X11 1
1546 if (!strncmp(PLAYER_INI()->videosink_element_x,"vaapisink", strlen("vaapisink"))){
1547 debug_log("set video param: vaapisink display %d", GST_VAAPI_DISPLAY_TYPE_X11);
1548 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1549 "display", GST_VAAPI_DISPLAY_TYPE_X11,
1553 debug_log("set video param : xid %d", *(int*)xid);
1554 #ifdef GST_API_VERSION_1
1555 gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
1557 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
1562 /* FIXIT : is it error case? */
1563 debug_warning("still we don't have xid on player attribute. create it's own surface.");
1566 /* if xvimagesink */
1567 if (!strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
1569 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
1570 mm_attrs_get_int_by_name(attrs, "display_zoom", &zoom);
1571 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1572 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1573 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1574 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1575 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1576 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1578 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1579 "force-aspect-ratio", force_aspect_ratio,
1581 "rotate", rotation_value,
1582 "handle-events", TRUE,
1583 "display-geometry-method", display_method,
1584 "draw-borders", FALSE,
1592 debug_log("set video param : zoom %d", zoom);
1593 debug_log("set video param : rotate %d", rotation_value);
1594 debug_log("set video param : method %d", display_method);
1595 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1596 roi_x, roi_y, roi_w, roi_h );
1597 debug_log("set video param : visible %d", visible);
1598 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
1602 if (!strncmp(PLAYER_INI()->videosink_element_x, "vaapisink", strlen("vaapisink")))
1604 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1605 "rotation", rotation_value,
1607 debug_log("set video param: vaapisink rotation %d", rotation_value);
1611 case MM_DISPLAY_SURFACE_EVAS:
1613 void *object = NULL;
1615 gboolean visible = TRUE;
1617 /* common case if using evas surface */
1618 mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
1619 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1620 mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
1623 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1624 "evas-object", object,
1627 debug_log("set video param : evas-object %x", object);
1628 debug_log("set video param : visible %d", visible);
1632 debug_error("no evas object");
1633 return MM_ERROR_PLAYER_INTERNAL;
1636 /* if evasimagesink */
1637 if (!strcmp(PLAYER_INI()->videosink_element_evas,"evasimagesink") && player->is_nv12_tiled)
1641 int no_scaling = !scaling;
1643 mm_attrs_get_int_by_name(attrs, "display_width", &width);
1644 mm_attrs_get_int_by_name(attrs, "display_height", &height);
1646 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
1647 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
1651 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
1652 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
1653 "dst-width", 0, /* setting 0, output video width will be media src's width */
1654 "dst-height", 0, /* setting 0, output video height will be media src's height */
1659 /* scaling order to fimcconvert */
1662 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1666 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1668 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
1670 debug_log("set video param : display_evas_do_scaling %d", scaling);
1673 /* if evaspixmapsink */
1674 if (!strcmp(PLAYER_INI()->videosink_element_evas,"evaspixmapsink"))
1676 int display_method = 0;
1681 int origin_size = !scaling;
1683 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1684 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1685 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1686 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1687 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1689 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1690 "origin-size", origin_size,
1695 "display-geometry-method", display_method,
1698 debug_log("set video param : method %d", display_method);
1699 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1700 roi_x, roi_y, roi_w, roi_h );
1701 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
1703 g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1706 case MM_DISPLAY_SURFACE_X_EXT: /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
1708 void *pixmap_id_cb = NULL;
1709 void *pixmap_id_cb_user_data = NULL;
1710 int display_method = 0;
1711 gboolean visible = TRUE;
1713 /* if xvimagesink */
1714 if (strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
1716 debug_error("videosink is not xvimagesink");
1717 return MM_ERROR_PLAYER_INTERNAL;
1720 /* get information from attributes */
1721 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
1722 mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
1723 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1727 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
1728 if (pixmap_id_cb_user_data)
1730 debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
1735 debug_error("failed to set pixmap-id-callback");
1736 return MM_ERROR_PLAYER_INTERNAL;
1738 debug_log("set video param : method %d", display_method);
1739 debug_log("set video param : visible %d", visible);
1741 /* set properties of videosink plugin */
1742 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1743 "display-geometry-method", display_method,
1744 "draw-borders", FALSE,
1746 "rotate", rotation_value,
1747 "pixmap-id-callback", pixmap_id_cb,
1748 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
1752 case MM_DISPLAY_SURFACE_NULL:
1761 return MM_ERROR_NONE;
1765 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
1767 mm_player_t* player = (mm_player_t*) u_data;
1771 #ifdef GST_API_VERSION_1
1773 gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1775 size = gst_buffer_get_size(buffer);
1777 if (player->audio_stream_cb && size && data)
1778 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
1780 gst_buffer_unmap (buffer, &info);
1782 data = GST_BUFFER_DATA(buffer);
1783 size = GST_BUFFER_SIZE(buffer);
1785 if (player->audio_stream_cb && size && data)
1786 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
1793 #ifdef GST_API_VERSION_1
1795 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
1797 mm_player_t* player = (mm_player_t*) data;
1798 MMMessageParamType msg = {0, };
1799 GstClockTime duration = 0;
1800 guint8 *text = NULL;
1801 gboolean ret = TRUE;
1806 return_val_if_fail ( player, FALSE );
1807 return_val_if_fail ( buffer, FALSE );
1809 gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1811 gst_buffer_unmap (buffer, &info);
1813 duration = GST_BUFFER_DURATION(buffer);
1815 if ( player->is_subtitle_off )
1817 debug_log("subtitle is OFF.\n" );
1823 debug_log("There is no subtitle to be displayed.\n" );
1827 msg.data = (void *) text;
1828 msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
1830 debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
1832 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
1840 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
1842 mm_player_t* player = (mm_player_t*) data;
1843 MMMessageParamType msg = {0, };
1844 GstClockTime duration = 0;
1845 guint8 *text = NULL;
1846 gboolean ret = TRUE;
1850 return_val_if_fail ( player, FALSE );
1851 return_val_if_fail ( buffer, FALSE );
1853 text = GST_BUFFER_DATA(buffer);
1854 duration = GST_BUFFER_DURATION(buffer);
1856 if ( player->is_subtitle_off )
1858 debug_log("subtitle is OFF.\n" );
1864 debug_log("There is no subtitle to be displayed.\n" );
1868 msg.data = (void *) text;
1869 msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
1871 debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
1873 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
1881 #ifdef GST_API_VERSION_1
1883 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
1885 mm_player_t* player = (mm_player_t*)hplayer;
1886 GstBuffer *buffer = NULL;
1888 GstFlowReturn gst_ret = GST_FLOW_OK;
1889 int ret = MM_ERROR_NONE;
1893 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1895 /* check current state */
1896 // MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
1899 /* NOTE : we should check and create pipeline again if not created as we destroy
1900 * whole pipeline when stopping in streamming playback
1902 if ( ! player->pipeline )
1904 if ( MM_ERROR_NONE != __gst_realize( player ) )
1906 debug_error("failed to realize before starting. only in streamming\n");
1907 return MM_ERROR_PLAYER_INTERNAL;
1911 debug_msg("app-src: pushing data\n");
1915 debug_error("buf is null\n");
1916 return MM_ERROR_NONE;
1919 buffer = gst_buffer_new ();
1923 debug_log("call eos appsrc\n");
1924 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
1925 return MM_ERROR_NONE;
1928 info.data = (guint8*)(buf);
1929 gst_buffer_set_size(buffer, size);
1930 gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1932 debug_log("feed buffer %p, length %u\n", buf, size);
1933 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
1941 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
1943 mm_player_t* player = (mm_player_t*)hplayer;
1944 GstBuffer *buffer = NULL;
1945 GstFlowReturn gst_ret = GST_FLOW_OK;
1946 int ret = MM_ERROR_NONE;
1950 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1952 /* check current state */
1953 // MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
1956 /* NOTE : we should check and create pipeline again if not created as we destroy
1957 * whole pipeline when stopping in streamming playback
1959 if ( ! player->pipeline )
1961 if ( MM_ERROR_NONE != __gst_realize( player ) )
1963 debug_error("failed to realize before starting. only in streamming\n");
1964 return MM_ERROR_PLAYER_INTERNAL;
1968 debug_msg("app-src: pushing data\n");
1972 debug_error("buf is null\n");
1973 return MM_ERROR_NONE;
1976 buffer = gst_buffer_new ();
1980 debug_log("call eos appsrc\n");
1981 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
1982 return MM_ERROR_NONE;
1985 GST_BUFFER_DATA(buffer) = (guint8*)(buf);
1986 GST_BUFFER_SIZE(buffer) = size;
1988 debug_log("feed buffer %p, length %u\n", buf, size);
1989 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
1998 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
2000 mm_player_t *player = (mm_player_t *)data;
2002 switch (GST_MESSAGE_TYPE (message))
2004 case GST_MESSAGE_TAG:
2005 __mmplayer_gst_extract_tag_from_msg(player, message);
2007 case GST_MESSAGE_DURATION:
2008 __mmplayer_gst_handle_duration(player, message);
2012 return GST_BUS_PASS;
2014 gst_message_unref (message);
2016 return GST_BUS_DROP;
2019 void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
2023 return_if_fail(player
2025 && player->pipeline->audiobin
2026 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
2028 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
2035 void __mmplayer_undo_sound_fadedown(mm_player_t* player)
2039 return_if_fail(player
2041 && player->pipeline->audiobin
2042 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
2044 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
2049 static gboolean __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
2051 gboolean ret = FALSE;
2056 return_val_if_fail ( uri , FALSE);
2057 return_val_if_fail ( data , FALSE);
2058 return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
2060 memset(data, 0, sizeof(MMPlayerParseProfile));
2062 if ((path = strstr(uri, "file://")))
2064 if (util_exist_file_path(path + 7)) {
2065 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
2067 if ( util_is_sdp_file ( path ) )
2069 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
2070 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2074 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
2080 debug_warning("could access %s.\n", path);
2083 else if ((path = strstr(uri, "buff://")))
2085 data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
2088 else if ((path = strstr(uri, "rtsp://")))
2091 strcpy(data->uri, uri);
2092 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2096 else if ((path = strstr(uri, "http://")))
2099 strcpy(data->uri, uri);
2100 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
2105 else if ((path = strstr(uri, "https://")))
2108 strcpy(data->uri, uri);
2109 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
2114 else if ((path = strstr(uri, "rtspu://")))
2117 strcpy(data->uri, uri);
2118 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2122 else if ((path = strstr(uri, "rtspr://")))
2124 strcpy(data->uri, path);
2125 char *separater =strstr(path, "*");
2129 char *urgent = separater + strlen("*");
2131 if ((urgent_len = strlen(urgent))) {
2132 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
2133 strcpy(data->urgent, urgent);
2134 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2139 else if ((path = strstr(uri, "mms://")))
2142 strcpy(data->uri, uri);
2143 data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
2147 else if ((path = strstr(uri, "mem://")))
2151 char *buffer = NULL;
2152 char *seperator = strchr(path, ',');
2153 char ext[100] = {0,}, size[100] = {0,};
2156 if ((buffer = strstr(path, "ext="))) {
2157 buffer += strlen("ext=");
2159 if (strlen(buffer)) {
2160 strcpy(ext, buffer);
2162 if ((seperator = strchr(ext, ','))
2163 || (seperator = strchr(ext, ' '))
2164 || (seperator = strchr(ext, '\0'))) {
2165 seperator[0] = '\0';
2170 if ((buffer = strstr(path, "size="))) {
2171 buffer += strlen("size=");
2173 if (strlen(buffer) > 0) {
2174 strcpy(size, buffer);
2176 if ((seperator = strchr(size, ','))
2177 || (seperator = strchr(size, ' '))
2178 || (seperator = strchr(size, '\0'))) {
2179 seperator[0] = '\0';
2182 mem_size = atoi(size);
2187 debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
2188 if ( mem_size && param) {
2190 data->mem_size = mem_size;
2191 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
2198 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
2199 if (util_exist_file_path(uri))
2201 debug_warning("uri has no protocol-prefix. giving 'file://' by default.\n");
2202 g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", uri);
2204 if ( util_is_sdp_file( (char*)uri ) )
2206 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
2207 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2211 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
2217 debug_error ("invalid uri, could not play..\n");
2218 data->uri_type = MM_PLAYER_URI_TYPE_NONE;
2222 if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
2226 /* dump parse result */
2227 debug_log("profile parsing result ---\n");
2228 debug_warning("incomming uri : %s\n", uri);
2229 debug_log("uri : %s\n", data->uri);
2230 debug_log("uri_type : %d\n", data->uri_type);
2231 debug_log("play_mode : %d\n", data->play_mode);
2232 debug_log("mem : 0x%x\n", (guint)data->mem);
2233 debug_log("mem_size : %d\n", data->mem_size);
2234 debug_log("urgent : %s\n", data->urgent);
2235 debug_log("--------------------------\n");
2242 gboolean _asm_postmsg(gpointer *data)
2244 mm_player_t* player = (mm_player_t*)data;
2245 MMMessageParamType msg = {0, };
2249 return_val_if_fail ( player, FALSE );
2251 msg.union_type = MM_MSG_UNION_CODE;
2252 msg.code = player->sm.event_src;
2254 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
2259 gboolean _asm_lazy_pause(gpointer *data)
2261 mm_player_t* player = (mm_player_t*)data;
2262 int ret = MM_ERROR_NONE;
2266 return_val_if_fail ( player, FALSE );
2268 if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
2270 debug_log ("Ready to proceed lazy pause\n");
2271 ret = _mmplayer_pause((MMHandleType)player);
2272 if(MM_ERROR_NONE != ret)
2274 debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
2279 debug_log ("Invalid state to proceed lazy pause\n");
2283 if (player->pipeline && player->pipeline->audiobin)
2284 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
2286 player->sm.by_asm_cb = 0; //should be reset here
2294 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
2296 mm_player_t* player = (mm_player_t*) cb_data;
2297 ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
2298 int result = MM_ERROR_NONE;
2299 gboolean lazy_pause = FALSE;
2303 return_val_if_fail ( player && player->pipeline, ASM_CB_RES_IGNORE );
2304 return_val_if_fail ( player->attrs, MM_ERROR_PLAYER_INTERNAL );
2306 if (player->is_sound_extraction)
2308 debug_log("sound extraction is working...so, asm command is ignored.\n");
2312 player->sm.by_asm_cb = 1; // it should be enabled for player state transition with called application command
2313 player->sm.event_src = event_src;
2315 if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG )
2317 int stop_by_asm = 0;
2319 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
2323 else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
2325 /* can use video overlay simultaneously */
2326 /* video resource conflict */
2327 if(player->pipeline->videobin)
2329 if (PLAYER_INI()->multiple_codec_supported)
2331 debug_log("video conflict but, can support to use video overlay simultaneously");
2332 result = _mmplayer_pause((MMHandleType)player);
2333 cb_res = ASM_CB_RES_PAUSE;
2337 debug_log("video conflict, can't support for multiple codec instance");
2338 result = _mmplayer_unrealize((MMHandleType)player);
2339 cb_res = ASM_CB_RES_STOP;
2347 case ASM_COMMAND_PLAY:
2348 debug_warning ("Got unexpected asm command (%d)", command);
2351 case ASM_COMMAND_STOP: // notification case
2353 debug_warning("Got msg from asm to stop");
2355 result = _mmplayer_stop((MMHandleType)player);
2356 if (result != MM_ERROR_NONE)
2358 debug_warning("fail to set stop state by asm");
2359 cb_res = ASM_CB_RES_IGNORE;
2363 cb_res = ASM_CB_RES_STOP;
2365 player->sm.by_asm_cb = 0; // reset because no message any more from asm
2369 case ASM_COMMAND_PAUSE:
2371 debug_warning("Got msg from asm to Pause");
2373 if(event_src == ASM_EVENT_SOURCE_CALL_START
2374 || event_src == ASM_EVENT_SOURCE_ALARM_START
2375 || event_src == ASM_EVENT_SOURCE_MEDIA)
2377 //hold 0.7 second to excute "fadedown mute" effect
2378 debug_warning ("do fade down->pause->undo fade down");
2380 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
2382 result = _mmplayer_pause((MMHandleType)player);
2383 if (result != MM_ERROR_NONE)
2385 debug_warning("fail to set Pause state by asm");
2386 cb_res = ASM_CB_RES_IGNORE;
2389 __mmplayer_undo_sound_fadedown(player);
2391 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
2393 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
2395 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
2396 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
2398 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
2399 debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
2404 debug_log ("immediate pause");
2405 result = _mmplayer_pause((MMHandleType)player);
2407 cb_res = ASM_CB_RES_PAUSE;
2411 case ASM_COMMAND_RESUME:
2413 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
2414 player->sm.by_asm_cb = 0;
2415 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
2416 g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
2417 cb_res = ASM_CB_RES_IGNORE;
2426 player->sm.by_asm_cb = 0;
2434 _mmplayer_create_player(MMHandleType handle) // @
2436 mm_player_t* player = MM_PLAYER_CAST(handle);
2440 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2442 MMTA_ACUM_ITEM_BEGIN("[KPI] media player service create->playing", FALSE);
2444 /* initialize player state */
2445 MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
2446 MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
2447 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
2448 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
2450 /* check current state */
2451 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
2453 /* construct attributes */
2454 player->attrs = _mmplayer_construct_attribute(handle);
2456 if ( !player->attrs )
2458 debug_critical("Failed to construct attributes\n");
2462 /* initialize gstreamer with configured parameter */
2463 if ( ! __mmplayer_gstreamer_init() )
2465 debug_critical("Initializing gstreamer failed\n");
2469 /* initialize factories if not using decodebin */
2470 if ( FALSE == PLAYER_INI()->use_decodebin )
2472 if( player->factories == NULL )
2473 __mmplayer_init_factories(player);
2476 /* create lock. note that g_tread_init() has already called in gst_init() */
2477 player->fsink_lock = g_mutex_new();
2478 if ( ! player->fsink_lock )
2480 debug_critical("Cannot create mutex for command lock\n");
2484 /* create repeat mutex */
2485 player->repeat_thread_mutex = g_mutex_new();
2486 if ( ! player->repeat_thread_mutex )
2488 debug_critical("Cannot create repeat mutex\n");
2492 /* create repeat cond */
2493 player->repeat_thread_cond = g_cond_new();
2494 if ( ! player->repeat_thread_cond )
2496 debug_critical("Cannot create repeat cond\n");
2500 /* create repeat thread */
2501 player->repeat_thread =
2502 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
2503 if ( ! player->repeat_thread )
2508 if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
2510 debug_error("failed to initialize video capture\n");
2514 /* register to asm */
2515 if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
2517 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
2518 debug_error("failed to register asm server\n");
2519 return MM_ERROR_POLICY_INTERNAL;
2522 if (MMPLAYER_IS_HTTP_PD(player))
2524 player->pd_downloader = NULL;
2525 player->pd_file_save_path = NULL;
2528 /* give default value of audio effect setting */
2529 player->bypass_audio_effect = TRUE;
2530 player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
2531 player->playback_rate = DEFAULT_PLAYBACK_RATE;
2533 player->play_subtitle = FALSE;
2534 player->use_textoverlay = FALSE;
2536 /* set player state to null */
2537 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
2538 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
2542 return MM_ERROR_NONE;
2546 if ( player->fsink_lock )
2547 g_mutex_free( player->fsink_lock );
2548 player->fsink_lock = NULL;
2551 if ( player->repeat_thread_cond &&
2552 player->repeat_thread_mutex &&
2553 player->repeat_thread )
2555 player->repeat_thread_exit = TRUE;
2556 g_cond_signal( player->repeat_thread_cond );
2558 g_thread_join( player->repeat_thread );
2559 player->repeat_thread = NULL;
2561 g_mutex_free ( player->repeat_thread_mutex );
2562 player->repeat_thread_mutex = NULL;
2564 g_cond_free ( player->repeat_thread_cond );
2565 player->repeat_thread_cond = NULL;
2567 /* clear repeat thread mutex/cond if still alive
2568 * this can happen if only thread creating has failed
2570 if ( player->repeat_thread_mutex )
2571 g_mutex_free ( player->repeat_thread_mutex );
2573 if ( player->repeat_thread_cond )
2574 g_cond_free ( player->repeat_thread_cond );
2576 /* release attributes */
2577 _mmplayer_deconstruct_attribute(handle);
2579 return MM_ERROR_PLAYER_INTERNAL;
2583 __mmplayer_gstreamer_init(void) // @
2585 static gboolean initialized = FALSE;
2586 static const int max_argc = 50;
2588 gchar** argv = NULL;
2596 debug_log("gstreamer already initialized.\n");
2601 argc = malloc( sizeof(int) );
2602 argv = malloc( sizeof(gchar*) * max_argc );
2604 if ( !argc || !argv )
2607 memset( argv, 0, sizeof(gchar*) * max_argc );
2611 argv[0] = g_strdup( "mmplayer" );
2614 for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
2616 if ( strlen( PLAYER_INI()->gst_param[i] ) > 0 )
2618 argv[*argc] = g_strdup( PLAYER_INI()->gst_param[i] );
2623 /* we would not do fork for scanning plugins */
2624 argv[*argc] = g_strdup("--gst-disable-registry-fork");
2627 /* check disable registry scan */
2628 if ( PLAYER_INI()->skip_rescan )
2630 argv[*argc] = g_strdup("--gst-disable-registry-update");
2634 /* check disable segtrap */
2635 if ( PLAYER_INI()->disable_segtrap )
2637 argv[*argc] = g_strdup("--gst-disable-segtrap");
2641 debug_log("initializing gstreamer with following parameter\n");
2642 debug_log("argc : %d\n", *argc);
2644 for ( i = 0; i < *argc; i++ )
2646 debug_log("argv[%d] : %s\n", i, argv[i]);
2650 /* initializing gstreamer */
2651 __ta__("gst_init time",
2653 if ( ! gst_init_check (argc, &argv, &err))
2655 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
2666 for ( i = 0; i < *argc; i++ )
2668 MMPLAYER_FREEIF( argv[i] );
2671 MMPLAYER_FREEIF( argv );
2672 MMPLAYER_FREEIF( argc );
2683 MMPLAYER_FREEIF( argv );
2684 MMPLAYER_FREEIF( argc );
2690 __mmplayer_destroy_streaming_ext(mm_player_t* player)
2692 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2694 if (player->pd_downloader)
2695 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
2697 if (MMPLAYER_IS_HTTP_PD(player))
2698 _mmplayer_destroy_pd_downloader((MMHandleType)player);
2700 if (MMPLAYER_IS_STREAMING(player))
2702 if (player->streamer)
2704 __mm_player_streaming_deinitialize (player->streamer);
2705 __mm_player_streaming_destroy(player->streamer);
2706 player->streamer = NULL;
2709 return MM_ERROR_NONE;
2713 _mmplayer_destroy(MMHandleType handle) // @
2715 mm_player_t* player = MM_PLAYER_CAST(handle);
2719 /* check player handle */
2720 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2722 /* destroy can called at anytime */
2723 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
2725 __mmplayer_destroy_streaming_ext(player);
2727 /* release repeat thread */
2728 if ( player->repeat_thread_cond &&
2729 player->repeat_thread_mutex &&
2730 player->repeat_thread )
2732 player->repeat_thread_exit = TRUE;
2733 g_cond_signal( player->repeat_thread_cond );
2735 debug_log("waitting for repeat thread exit\n");
2736 g_thread_join ( player->repeat_thread );
2737 g_mutex_free ( player->repeat_thread_mutex );
2738 g_cond_free ( player->repeat_thread_cond );
2739 debug_log("repeat thread released\n");
2742 if (MM_ERROR_NONE != _mmplayer_release_video_capture(player))
2744 debug_error("failed to release video capture\n");
2745 return MM_ERROR_PLAYER_INTERNAL;
2749 if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
2751 debug_error("failed to deregister asm server\n");
2752 return MM_ERROR_PLAYER_INTERNAL;
2755 /* release pipeline */
2756 if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
2758 debug_error("failed to destory pipeline\n");
2759 return MM_ERROR_PLAYER_INTERNAL;
2762 /* release attributes */
2763 _mmplayer_deconstruct_attribute( handle );
2765 /* release factories */
2766 __mmplayer_release_factories( player );
2769 if ( player->fsink_lock )
2770 g_mutex_free( player->fsink_lock );
2772 if ( player->msg_cb_lock )
2773 g_mutex_free( player->msg_cb_lock );
2775 if (player->lazy_pause_event_id)
2777 g_source_remove (player->lazy_pause_event_id);
2778 player->lazy_pause_event_id = 0;
2783 return MM_ERROR_NONE;
2787 __mmplayer_realize_streaming_ext(mm_player_t* player)
2789 int ret = MM_ERROR_NONE;
2792 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2794 if (MMPLAYER_IS_HTTP_PD(player))
2796 gboolean bret = FALSE;
2798 player->pd_downloader = _mmplayer_create_pd_downloader();
2799 if ( !player->pd_downloader )
2801 debug_error ("Unable to create PD Downloader...");
2802 ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
2805 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
2809 debug_error ("Unable to create PD Downloader...");
2810 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
2819 _mmplayer_realize(MMHandleType hplayer) // @
2821 mm_player_t* player = (mm_player_t*)hplayer;
2824 int application_pid = -1;
2825 gboolean update_registry = FALSE;
2826 MMHandleType attrs = 0;
2827 int ret = MM_ERROR_NONE;
2831 /* check player handle */
2832 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
2834 /* check current state */
2835 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
2837 attrs = MMPLAYER_GET_ATTRS(player);
2840 debug_error("fail to get attributes.\n");
2841 return MM_ERROR_PLAYER_INTERNAL;
2844 mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
2845 player->sm.pid = application_pid;
2847 mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
2848 mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m);
2850 if (! __mmfplayer_parse_profile((const char*)uri, param, &player->profile) )
2852 debug_error("failed to parse profile\n");
2853 return MM_ERROR_PLAYER_INVALID_URI;
2856 /* FIXIT : we can use thouse in player->profile directly */
2857 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
2859 player->mem_buf.buf = (char *)player->profile.mem;
2860 player->mem_buf.len = player->profile.mem_size;
2861 player->mem_buf.offset = 0;
2864 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
2866 debug_warning("mms protocol is not supported format.\n");
2867 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
2870 if (MMPLAYER_IS_STREAMING(player))
2871 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->live_state_change_timeout;
2873 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
2875 player->videodec_linked = 0;
2876 player->videosink_linked = 0;
2877 player->audiodec_linked = 0;
2878 player->audiosink_linked = 0;
2879 player->textsink_linked = 0;
2881 /* set the subtitle ON default */
2882 player->is_subtitle_off = FALSE;
2884 /* registry should be updated for downloadable codec */
2885 mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
2887 if ( update_registry )
2889 debug_log("updating registry...\n");
2890 gst_update_registry();
2892 /* then we have to rebuild factories */
2893 __mmplayer_release_factories( player );
2894 __mmplayer_init_factories(player);
2897 /* realize pipeline */
2898 ret = __gst_realize( player );
2899 if ( ret != MM_ERROR_NONE )
2901 debug_error("fail to realize the player.\n");
2905 ret = __mmplayer_realize_streaming_ext(player);
2914 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
2917 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2919 /* destroy can called at anytime */
2920 if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
2922 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
2923 player->pd_downloader = NULL;
2927 return MM_ERROR_NONE;
2931 _mmplayer_unrealize(MMHandleType hplayer) // @
2933 mm_player_t* player = (mm_player_t*)hplayer;
2934 int ret = MM_ERROR_NONE;
2938 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
2940 /* check current state */
2941 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
2943 __mmplayer_unrealize_streaming_ext(player);
2945 /* unrealize pipeline */
2946 ret = __gst_unrealize( player );
2948 /* set player state if success */
2949 if ( MM_ERROR_NONE == ret )
2951 if (player->sm.state != ASM_STATE_STOP) {
2952 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP);
2955 debug_error("failed to set asm state to STOP\n");
2967 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
2969 mm_player_t* player = (mm_player_t*)hplayer;
2971 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
2973 return __gst_set_message_callback(player, callback, user_param);
2977 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
2979 mm_player_t *player = (mm_player_t*)hplayer;
2981 return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
2983 *state = MMPLAYER_CURRENT_STATE(player);
2985 return MM_ERROR_NONE;
2990 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
2992 mm_player_t* player = (mm_player_t*) hplayer;
2993 GstElement* vol_element = NULL;
2998 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3000 debug_log("volume [L]=%f:[R]=%f\n",
3001 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
3003 /* invalid factor range or not */
3004 for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
3006 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
3007 debug_error("Invalid factor! (valid factor:0~1.0)\n");
3008 return MM_ERROR_INVALID_ARGUMENT;
3012 /* Save volume to handle. Currently the first array element will be saved. */
3013 player->sound.volume = volume.level[0];
3015 /* check pipeline handle */
3016 if ( ! player->pipeline || ! player->pipeline->audiobin )
3018 debug_log("audiobin is not created yet\n");
3019 debug_log("but, current stored volume will be set when it's created.\n");
3021 /* NOTE : stored volume will be used in create_audiobin
3022 * returning MM_ERROR_NONE here makes application to able to
3023 * set volume at anytime.
3025 return MM_ERROR_NONE;
3028 /* setting volume to volume element */
3029 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3033 debug_log("volume is set [%f]\n", player->sound.volume);
3034 g_object_set(vol_element, "volume", player->sound.volume, NULL);
3039 return MM_ERROR_NONE;
3044 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
3046 mm_player_t* player = (mm_player_t*) hplayer;
3051 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3052 return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
3054 /* returning stored volume */
3055 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
3056 volume->level[i] = player->sound.volume;
3060 return MM_ERROR_NONE;
3066 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
3068 mm_player_t* player = (mm_player_t*) hplayer;
3069 GstElement* vol_element = NULL;
3073 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3075 debug_log("mute : %d\n", mute);
3077 /* mute value shoud 0 or 1 */
3078 if ( mute != 0 && mute != 1 )
3080 debug_error("bad mute value\n");
3082 /* FIXIT : definitly, we need _BAD_PARAM error code */
3083 return MM_ERROR_INVALID_ARGUMENT;
3087 /* just hold mute value if pipeline is not ready */
3088 if ( !player->pipeline || !player->pipeline->audiobin )
3090 debug_log("pipeline is not ready. holding mute value\n");
3091 player->sound.mute = mute;
3092 return MM_ERROR_NONE;
3096 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3098 /* NOTE : volume will only created when the bt is enabled */
3101 g_object_set(vol_element, "mute", mute, NULL);
3105 debug_log("volume elemnet is not created. using volume in audiosink\n");
3108 player->sound.mute = mute;
3112 return MM_ERROR_NONE;
3116 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
3118 mm_player_t* player = (mm_player_t*) hplayer;
3119 GstElement* vol_element = NULL;
3123 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3124 return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
3126 /* just hold mute value if pipeline is not ready */
3127 if ( !player->pipeline || !player->pipeline->audiobin )
3129 debug_log("pipeline is not ready. returning stored value\n");
3130 *pmute = player->sound.mute;
3131 return MM_ERROR_NONE;
3135 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3139 g_object_get(vol_element, "mute", pmute, NULL);
3140 debug_log("mute=%d\n\n", *pmute);
3144 *pmute = player->sound.mute;
3149 return MM_ERROR_NONE;
3153 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
3155 mm_player_t* player = (mm_player_t*) hplayer;
3159 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3160 return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
3162 player->video_stream_cb = callback;
3163 player->video_stream_cb_user_param = user_param;
3164 player->use_video_stream = TRUE;
3165 debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
3169 return MM_ERROR_NONE;
3173 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
3175 mm_player_t* player = (mm_player_t*) hplayer;
3179 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3180 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3182 player->audio_stream_cb = callback;
3183 player->audio_stream_cb_user_param = user_param;
3184 debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
3188 return MM_ERROR_NONE;
3192 _mmplayer_set_audiobuffer_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
3194 mm_player_t* player = (mm_player_t*) hplayer;
3198 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3199 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3201 player->audio_buffer_cb = callback;
3202 player->audio_buffer_cb_user_param = user_param;
3203 debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_buffer_cb);
3207 return MM_ERROR_NONE;
3211 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
3213 mm_player_t* player = (mm_player_t*) hplayer;
3217 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3218 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3220 player->need_data_cb = callback;
3221 player->buffer_cb_user_param = user_param;
3223 debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
3227 return MM_ERROR_NONE;
3231 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
3233 mm_player_t* player = (mm_player_t*) hplayer;
3237 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3238 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3240 player->enough_data_cb = callback;
3241 player->buffer_cb_user_param = user_param;
3243 debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
3247 return MM_ERROR_NONE;
3251 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
3253 mm_player_t* player = (mm_player_t*) hplayer;
3257 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3258 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3260 player->seek_data_cb = callback;
3261 player->buffer_cb_user_param = user_param;
3263 debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
3267 return MM_ERROR_NONE;
3271 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
3273 mm_player_t* player = (mm_player_t*) hplayer;
3277 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3278 return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
3280 player->video_frame_render_error_cb = callback;
3281 player->video_frame_render_error_cb_user_param = user_param;
3283 debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
3287 return MM_ERROR_NONE;
3291 __mmplayer_start_streaming_ext(mm_player_t *player)
3293 gint ret = MM_ERROR_NONE;
3296 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3298 if (MMPLAYER_IS_HTTP_PD(player))
3300 if ( !player->pd_downloader )
3302 ret = __mmplayer_realize_streaming_ext(player);
3304 if ( ret != MM_ERROR_NONE)
3306 debug_error ("failed to realize streaming ext\n");
3311 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
3313 ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
3316 debug_error ("ERROR while starting PD...\n");
3317 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3319 ret = MM_ERROR_NONE;
3328 _mmplayer_start(MMHandleType hplayer) // @
3330 mm_player_t* player = (mm_player_t*) hplayer;
3331 gint ret = MM_ERROR_NONE;
3335 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3337 /* check current state */
3338 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
3340 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
3341 if ( ret != MM_ERROR_NONE )
3343 debug_error("failed to set asm state to PLAYING\n");
3347 /* NOTE : we should check and create pipeline again if not created as we destroy
3348 * whole pipeline when stopping in streamming playback
3350 if ( ! player->pipeline )
3352 ret = __gst_realize( player );
3353 if ( MM_ERROR_NONE != ret )
3355 debug_error("failed to realize before starting. only in streamming\n");
3360 ret = __mmplayer_start_streaming_ext(player);
3361 if ( ret != MM_ERROR_NONE )
3363 debug_error("failed to start streaming ext \n");
3366 /* start pipeline */
3367 ret = __gst_start( player );
3368 if ( ret != MM_ERROR_NONE )
3370 debug_error("failed to start player.\n");
3378 /* NOTE : it should be able to call 'stop' anytime*/
3380 _mmplayer_stop(MMHandleType hplayer) // @
3382 mm_player_t* player = (mm_player_t*)hplayer;
3383 int ret = MM_ERROR_NONE;
3387 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3389 /* check current state */
3390 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
3392 /* NOTE : application should not wait for EOS after calling STOP */
3393 __mmplayer_cancel_delayed_eos( player );
3395 __mmplayer_unrealize_streaming_ext(player);
3398 ret = __gst_stop( player );
3400 if ( ret != MM_ERROR_NONE )
3402 debug_error("failed to stop player.\n");
3411 _mmplayer_pause(MMHandleType hplayer) // @
3413 mm_player_t* player = (mm_player_t*)hplayer;
3414 #ifndef GST_API_VERSION_1
3415 GstFormat fmt = GST_FORMAT_TIME;
3417 gint64 pos_msec = 0;
3418 gboolean async = FALSE;
3419 gint ret = MM_ERROR_NONE;
3423 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3425 /* check current state */
3426 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
3428 switch (MMPLAYER_CURRENT_STATE(player))
3430 case MM_PLAYER_STATE_READY:
3432 /* check prepare async or not.
3433 * In the case of streaming playback, it's recommned to avoid blocking wait.
3435 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
3436 debug_log("prepare mode : %s", (async ? "async" : "sync"));
3440 case MM_PLAYER_STATE_PLAYING:
3442 /* NOTE : store current point to overcome some bad operation
3443 * ( returning zero when getting current position in paused state) of some
3446 #ifdef GST_API_VERSION_1
3447 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
3449 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
3452 debug_warning("getting current position failed in paused\n");
3454 player->last_position = pos_msec;
3459 /* pause pipeline */
3460 ret = __gst_pause( player, async );
3462 if ( ret != MM_ERROR_NONE )
3464 debug_error("failed to pause player. ret : 0x%x\n", ret);
3473 _mmplayer_resume(MMHandleType hplayer)
3475 mm_player_t* player = (mm_player_t*)hplayer;
3476 int ret = MM_ERROR_NONE;
3477 gboolean async = FALSE;
3481 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3483 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
3486 debug_error("failed to set asm state to PLAYING\n");
3490 /* check current state */
3491 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
3493 /* resume pipeline */
3494 ret = __gst_resume( player, FALSE );
3496 if ( ret != MM_ERROR_NONE )
3498 debug_error("failed to resume player.\n");
3508 __mmplayer_set_play_count(mm_player_t* player, gint count)
3510 MMHandleType attrs = 0;
3514 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3516 attrs = MMPLAYER_GET_ATTRS(player);
3519 debug_error("fail to get attributes.\n");
3520 return MM_ERROR_PLAYER_INTERNAL;
3523 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
3524 if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
3525 debug_error("failed to commit\n");
3529 return MM_ERROR_NONE;
3533 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
3535 mm_player_t* player = (mm_player_t*)hplayer;
3536 gint64 start_pos = 0;
3542 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3543 return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
3545 player->section_repeat = TRUE;
3546 player->section_repeat_start = start;
3547 player->section_repeat_end = end;
3549 start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
3550 end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
3552 __mmplayer_set_play_count( player, infinity );
3554 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3555 player->playback_rate,
3557 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3558 GST_SEEK_TYPE_SET, start_pos,
3559 GST_SEEK_TYPE_SET, end_pos)))
3561 debug_error("failed to activate section repeat\n");
3563 return MM_ERROR_PLAYER_SEEK;
3566 debug_log("succeeded to set section repeat from %d to %d\n",
3567 player->section_repeat_start, player->section_repeat_end);
3571 return MM_ERROR_NONE;
3575 __mmplayer_set_pcm_extraction(mm_player_t* player)
3577 guint64 start_nsec = 0;
3578 guint64 end_nsec = 0;
3579 guint64 dur_nsec = 0;
3580 guint64 dur_msec = 0;
3581 #ifndef GST_API_VERSION_1
3582 GstFormat fmt = GST_FORMAT_TIME;
3584 int required_start = 0;
3585 int required_end = 0;
3590 return_val_if_fail( player, FALSE );
3592 mm_attrs_multiple_get(player->attrs,
3594 "pcm_extraction_start_msec", &required_start,
3595 "pcm_extraction_end_msec", &required_end,
3598 debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
3600 if (required_start == 0 && required_end == 0)
3602 debug_log("extracting entire stream");
3603 return MM_ERROR_NONE;
3605 else if (required_start < 0 || required_start > required_end || required_end < 0 )
3607 debug_log("invalid range for pcm extraction");
3608 return MM_ERROR_INVALID_ARGUMENT;
3612 #ifdef GST_API_VERSION_1
3613 ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
3615 ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
3619 debug_error("failed to get duration");
3620 return MM_ERROR_PLAYER_INTERNAL;
3622 dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
3624 if (dur_msec < required_end) // FIXME
3626 debug_log("invalid end pos for pcm extraction");
3627 return MM_ERROR_INVALID_ARGUMENT;
3630 start_nsec = required_start * G_GINT64_CONSTANT(1000000);
3631 end_nsec = required_end * G_GINT64_CONSTANT(1000000);
3633 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3636 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3637 GST_SEEK_TYPE_SET, start_nsec,
3638 GST_SEEK_TYPE_SET, end_nsec)))
3640 debug_error("failed to seek for pcm extraction\n");
3642 return MM_ERROR_PLAYER_SEEK;
3645 debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
3649 return MM_ERROR_NONE;
3653 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
3655 mm_player_t* player = (mm_player_t*)hplayer;
3657 #ifndef GST_API_VERSION_1
3658 GstFormat fmt = GST_FORMAT_TIME;
3664 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3666 player->section_repeat = FALSE;
3668 __mmplayer_set_play_count( player, onetime );
3669 #ifdef GST_API_VERSION_1
3670 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
3672 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
3675 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3678 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3679 GST_SEEK_TYPE_SET, cur_pos,
3680 GST_SEEK_TYPE_SET, player->duration )))
3682 debug_error("failed to deactivate section repeat\n");
3684 return MM_ERROR_PLAYER_SEEK;
3689 return MM_ERROR_NONE;
3693 _mmplayer_set_playspeed(MMHandleType hplayer, gdouble rate)
3695 mm_player_t* player = (mm_player_t*)hplayer;
3696 signed long long pos_msec = 0;
3697 int ret = MM_ERROR_NONE;
3699 #ifndef GST_API_VERSION_1
3700 GstFormat format =GST_FORMAT_TIME;
3702 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
3705 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3706 return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
3708 /* The sound of video is not supported under 0.0 and over 2.0. */
3709 if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
3711 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
3714 _mmplayer_set_mute(hplayer, mute);
3716 if (player->playback_rate == rate)
3717 return MM_ERROR_NONE;
3719 /* If the position is reached at start potion during fast backward, EOS is posted.
3720 * So, This EOS have to be classified with it which is posted at reaching the end of stream.
3722 player->playback_rate = rate;
3724 current_state = MMPLAYER_CURRENT_STATE(player);
3725 #ifdef GST_API_VERSION_1
3726 if ( current_state != MM_PLAYER_STATE_PAUSED )
3727 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
3729 if ( current_state != MM_PLAYER_STATE_PAUSED )
3730 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
3733 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
3735 if ( ( current_state == MM_PLAYER_STATE_PAUSED )
3737 //|| ( player->last_position != 0 && pos_msec == 0 ) )
3739 debug_warning("returning last point : %lld\n", player->last_position );
3740 pos_msec = player->last_position;
3743 if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3746 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3747 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
3748 GST_SEEK_TYPE_SET, pos_msec,
3749 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
3750 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
3752 debug_error("failed to set speed playback\n");
3753 return MM_ERROR_PLAYER_SEEK;
3756 debug_log("succeeded to set speed playback as %fl\n", rate);
3760 return MM_ERROR_NONE;;
3764 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
3766 mm_player_t* player = (mm_player_t*)hplayer;
3767 int ret = MM_ERROR_NONE;
3771 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3773 ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
3781 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
3783 mm_player_t* player = (mm_player_t*)hplayer;
3784 int ret = MM_ERROR_NONE;
3786 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3788 ret = __gst_get_position ( player, format, position );
3794 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
3796 mm_player_t* player = (mm_player_t*)hplayer;
3797 int ret = MM_ERROR_NONE;
3799 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3801 ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
3807 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
3809 mm_player_t* player = (mm_player_t*)hplayer;
3810 int ret = MM_ERROR_NONE;
3814 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3816 ret = __gst_adjust_subtitle_position(player, format, position);
3824 __mmplayer_is_midi_type( gchar* str_caps)
3826 if ( ( g_strrstr(str_caps, "audio/midi") ) ||
3827 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
3828 ( g_strrstr(str_caps, "application/x-smaf") ) ||
3829 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
3830 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
3831 ( g_strrstr(str_caps, "audio/xmf") ) ||
3832 ( g_strrstr(str_caps, "audio/mxmf") ) )
3834 debug_log("midi\n");
3843 __mmplayer_is_amr_type (gchar *str_caps)
3845 if ((g_strrstr(str_caps, "AMR")) ||
3846 (g_strrstr(str_caps, "amr")))
3854 __mmplayer_is_only_mp3_type (gchar *str_caps)
3856 if (g_strrstr(str_caps, "application/x-id3") ||
3857 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
3865 __mmplayer_typefind_have_type( GstElement *tf, guint probability, // @
3866 GstCaps *caps, gpointer data)
3868 mm_player_t* player = (mm_player_t*)data;
3873 return_if_fail( player && tf && caps );
3875 /* store type string */
3876 MMPLAYER_FREEIF(player->type);
3877 player->type = gst_caps_to_string(caps);
3879 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
3881 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
3882 if ( __mmplayer_is_midi_type(player->type))
3884 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
3886 else if (__mmplayer_is_amr_type(player->type))
3888 player->bypass_audio_effect = FALSE;
3889 if ( (PLAYER_INI()->use_audio_effect_preset || PLAYER_INI()->use_audio_effect_custom) )
3891 if ( player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_PRESET )
3893 if (!_mmplayer_audio_effect_preset_apply(player, player->audio_effect_info.preset))
3895 debug_msg("apply audio effect(preset:%d) setting success\n",player->audio_effect_info.preset);
3898 else if ( player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM )
3900 if (!_mmplayer_audio_effect_custom_apply(player))
3902 debug_msg("apply audio effect(custom) setting success\n");
3907 else if ( g_strrstr(player->type, "application/x-hls"))
3909 /* If it can't know exact type when it parses uri because of redirection case,
3910 * it will be fixed by typefinder here.
3912 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
3915 pad = gst_element_get_static_pad(tf, "src");
3918 debug_error("fail to get typefind src pad.\n");
3923 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
3925 gboolean async = FALSE;
3927 debug_error("failed to autoplug %s\n", player->type);
3928 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
3930 if ( async && player->msg_posted == FALSE )
3932 __mmplayer_handle_missed_plugin( player );
3938 /* finish autopluging if no dynamic pad waiting */
3939 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
3941 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
3943 __mmplayer_pipeline_complete( NULL, (gpointer)player );
3948 gst_object_unref( GST_OBJECT(pad) );
3956 __mmplayer_warm_up_video_codec( mm_player_t* player, GstElementFactory *factory)
3958 GstElement *element;
3959 GstStateChangeReturn ret;
3960 gboolean usable = TRUE;
3962 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3963 return_val_if_fail ( factory, MM_ERROR_COMMON_INVALID_ARGUMENT );
3965 element = gst_element_factory_create (factory, NULL);
3967 ret = gst_element_set_state (element, GST_STATE_READY);
3969 if (ret != GST_STATE_CHANGE_SUCCESS)
3971 #ifdef GST_API_VERSION_1
3972 debug_error ("resource conflict so, %s unusable\n", gst_object_get_name (GST_OBJECT (factory)));
3974 debug_error ("resource conflict so, %s unusable\n", GST_PLUGIN_FEATURE_NAME (factory));
3979 gst_element_set_state (element, GST_STATE_NULL);
3980 gst_object_unref (element);
3985 /* it will return first created element */
3987 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
3989 MMPlayerGstElement* mainbin = NULL;
3990 const char* mime = NULL;
3991 const GList* item = NULL;
3992 const gchar* klass = NULL;
3993 GstCaps* res = NULL;
3994 gboolean skip = FALSE;
3995 GstPad* queue_pad = NULL;
3996 GstElement* queue = NULL;
3997 GstElement *element = NULL;
4001 return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
4003 mainbin = player->pipeline->mainbin;
4005 mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
4007 /* return if we got raw output */
4008 if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
4009 || g_str_has_prefix(mime, "video/x-surface")
4010 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
4013 element = (GstElement*)gst_pad_get_parent(pad);
4014 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
4015 * No queue will be added. I think it can caused breaking sound when playing raw audio
4016 * frames but there's no different. Decodebin also doesn't add with those wav fils.
4017 * Anyway, currentely raw-queue seems not necessary.
4020 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
4021 * has linked. if so, we need to add queue for quality of output. note that
4022 * decodebin also has same problem.
4024 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
4026 /* add queue if needed */
4027 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
4028 || g_strrstr(klass, "Parse")) && !g_str_has_prefix(mime, "text"))
4030 debug_log("adding raw queue\n");
4032 queue = gst_element_factory_make("queue", NULL);
4035 debug_warning("failed to create queue\n");
4040 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
4042 debug_warning("failed to set state READY to queue\n");
4046 /* add to pipeline */
4047 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
4049 debug_warning("failed to add queue\n");
4054 queue_pad = gst_element_get_static_pad(queue, "sink");
4056 if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
4058 debug_warning("failed to link queue\n");
4061 gst_object_unref ( GST_OBJECT(queue_pad) );
4065 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
4067 debug_warning("failed to set state READY to queue\n");
4071 /* replace given pad to queue:src */
4072 pad = gst_element_get_static_pad(queue, "src");
4075 debug_warning("failed to get pad from queue\n");
4080 /* check if player can do start continually */
4081 MMPLAYER_CHECK_CMD_IF_EXIT(player);
4083 if(__mmplayer_link_sink(player,pad))
4084 __mmplayer_gst_decode_callback(element, pad, FALSE, player);
4086 gst_object_unref( GST_OBJECT(element));
4092 item = player->factories;
4093 for(; item != NULL ; item = item->next)
4095 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
4101 /* filtering exclude keyword */
4102 #ifdef GST_API_VERSION_1
4103 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
4105 if ( g_strrstr(gst_object_get_name (GST_OBJECT (factory)),
4106 PLAYER_INI()->exclude_element_keyword[idx]) )
4108 debug_warning("skipping [%s] by exculde keyword [%s]\n",
4109 gst_object_get_name (GST_OBJECT (factory)),
4110 PLAYER_INI()->exclude_element_keyword[idx] );
4117 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
4119 if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
4120 PLAYER_INI()->exclude_element_keyword[idx] ) )
4122 debug_warning("skipping [%s] by exculde keyword [%s]\n",
4123 GST_PLUGIN_FEATURE_NAME (factory),
4124 PLAYER_INI()->exclude_element_keyword[idx] );
4132 if ( skip ) continue;
4134 /* check factory class for filtering */
4135 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
4137 /* NOTE : msl don't need to use image plugins.
4138 * So, those plugins should be skipped for error handling.
4140 if ( g_strrstr(klass, "Codec/Decoder/Image") )
4142 #ifdef GST_API_VERSION_1
4143 debug_log("skipping [%s] by not required\n",
4144 gst_object_get_name (GST_OBJECT (factory)) );
4146 debug_log("skipping [%s] by not required\n",
4147 GST_PLUGIN_FEATURE_NAME (factory) );
4152 /* check pad compatability */
4153 for(pads = gst_element_factory_get_static_pad_templates(factory);
4154 pads != NULL; pads=pads->next)
4156 GstStaticPadTemplate *temp1 = pads->data;
4157 GstCaps* static_caps = NULL;
4159 if( temp1->direction != GST_PAD_SINK ||
4160 temp1->presence != GST_PAD_ALWAYS)
4163 if ( GST_IS_CAPS( &temp1->static_caps.caps) )
4165 /* using existing caps */
4166 static_caps = gst_caps_ref( &temp1->static_caps.caps );
4171 static_caps = gst_caps_from_string ( temp1->static_caps.string );
4174 res = gst_caps_intersect(caps, static_caps);
4176 gst_caps_unref( static_caps );
4179 if( res && !gst_caps_is_empty(res) )
4181 #ifdef GST_API_VERSION_1
4182 GstElement *new_element;
4183 GList *elements = player->parsers;
4184 char *name_template = g_strdup(temp1->name_template);
4185 gchar *name_to_plug = gst_object_get_name (GST_OBJECT (factory));
4187 gst_caps_unref(res);
4189 debug_log("found %s to plug\n", name_to_plug);
4191 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
4192 if ( ! new_element )
4194 debug_error("failed to create element [%s]. continue with next.\n",
4195 gst_object_get_name (GST_OBJECT (factory)));
4197 MMPLAYER_FREEIF(name_template);
4202 GstElement *new_element;
4203 GList *elements = player->parsers;
4204 char *name_template = g_strdup(temp1->name_template);
4205 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
4207 gst_caps_unref(res);
4209 debug_log("found %s to plug\n", name_to_plug);
4211 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
4212 if ( ! new_element )
4214 debug_error("failed to create element [%s]. continue with next.\n",
4215 GST_PLUGIN_FEATURE_NAME (factory));
4217 MMPLAYER_FREEIF(name_template);
4223 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
4224 * because parser can accept its own output as input.
4226 if (g_strrstr(klass, "Parser"))
4228 gchar *selected = NULL;
4230 for ( ; elements; elements = g_list_next(elements))
4232 gchar *element_name = elements->data;
4234 if (g_strrstr(element_name, name_to_plug))
4236 debug_log("but, %s already linked, so skipping it\n", name_to_plug);
4243 selected = g_strdup(name_to_plug);
4245 player->parsers = g_list_append(player->parsers, selected);
4248 /* store specific handles for futher control */
4249 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
4251 /* FIXIT : first value will be overwritten if there's more
4252 * than 1 demuxer/parser
4254 debug_log("plugged element is demuxer. take it\n");
4255 mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
4256 mainbin[MMPLAYER_M_DEMUX].gst = new_element;
4258 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
4260 if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
4262 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
4263 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
4264 mainbin[MMPLAYER_M_DEC1].gst = new_element;
4266 else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
4268 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
4269 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
4270 mainbin[MMPLAYER_M_DEC2].gst = new_element;
4272 /* NOTE : IF one codec is found, add it to supported_codec and remove from
4273 * missing plugin. Both of them are used to check what's supported codec
4274 * before returning result of play start. And, missing plugin should be
4275 * updated here for multi track files.
4277 if(g_str_has_prefix(mime, "video"))
4279 GstPad *src_pad = NULL;
4280 GstPadTemplate *pad_templ = NULL;
4281 GstCaps *caps = NULL;
4282 gchar *caps_type = NULL;
4284 debug_log("found VIDEO decoder\n");
4285 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
4286 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
4288 src_pad = gst_element_get_static_pad (new_element, "src");
4289 pad_templ = gst_pad_get_pad_template (src_pad);
4290 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
4292 caps_type = gst_caps_to_string(caps);
4294 if ( g_strrstr( caps_type, "ST12") )
4295 player->is_nv12_tiled = TRUE;
4298 MMPLAYER_FREEIF( caps_type );
4299 gst_object_unref (src_pad);
4301 else if (g_str_has_prefix(mime, "audio"))
4303 debug_log("found AUDIO decoder\n");
4304 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
4305 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
4308 if ( ! __mmplayer_close_link(player, pad, new_element,
4309 name_template,gst_element_factory_get_static_pad_templates(factory)) )
4311 if (player->keep_detecting_vcodec)
4314 /* Link is failed even though a supportable codec is found. */
4315 __mmplayer_check_not_supported_codec(player, (gchar *)mime);
4317 MMPLAYER_FREEIF(name_template);
4318 debug_error("failed to call _close_link\n");
4322 MMPLAYER_FREEIF(name_template);
4326 gst_caps_unref(res);
4332 /* There is no available codec. */
4333 __mmplayer_check_not_supported_codec(player,(gchar *)mime);
4342 gst_object_unref( queue );
4346 gst_object_unref( queue_pad );
4349 gst_object_unref ( element );
4356 int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime)
4360 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4361 return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
4363 debug_log("mimetype to check: %s\n", mime );
4365 /* add missing plugin */
4366 /* NOTE : msl should check missing plugin for image mime type.
4367 * Some motion jpeg clips can have playable audio track.
4368 * So, msl have to play audio after displaying popup written video format not supported.
4370 if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
4372 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
4374 debug_log("not found demuxer\n");
4375 player->not_found_demuxer = TRUE;
4376 player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
4382 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
4384 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
4385 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
4387 /* check that clip have multi tracks or not */
4388 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
4390 debug_log("video plugin is already linked\n");
4394 debug_warning("add VIDEO to missing plugin\n");
4395 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
4398 else if ( g_str_has_prefix(mime, "audio") )
4400 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
4402 debug_log("audio plugin is already linked\n");
4406 debug_warning("add AUDIO to missing plugin\n");
4407 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
4414 return MM_ERROR_NONE;
4418 void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) // @
4420 mm_player_t* player = (mm_player_t*)data;
4424 return_if_fail( player );
4426 /* remove fakesink */
4427 if ( ! __mmplayer_gst_remove_fakesink( player,
4428 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
4430 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
4431 * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
4432 * source element are not same. To overcome this situation, this function will called
4433 * several places and several times. Therefore, this is not an error case.
4437 debug_log("pipeline has completely constructed\n");
4439 player->pipeline_is_constructed = TRUE;
4441 if ( ( PLAYER_INI()->async_start ) &&
4442 ( player->msg_posted == FALSE ) &&
4443 ( player->cmd >= MMPLAYER_COMMAND_START ))
4445 __mmplayer_handle_missed_plugin( player );
4448 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
4451 gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
4455 return_val_if_fail ( player, FALSE );
4458 if ( MMPLAYER_IS_STREAMING(player) )
4461 /* This callback can be set to music player only. */
4462 if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
4464 debug_warning("audio callback is not supported for video");
4468 if (player->audio_stream_cb)
4473 #ifdef GST_API_VERSION_1
4474 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
4476 pad = gst_element_get_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
4481 debug_error("failed to get sink pad from audiosink to probe data\n");
4485 #ifdef GST_API_VERSION_1
4486 player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
4487 __mmplayer_audio_stream_probe, player, NULL);
4489 player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
4490 G_CALLBACK (__mmplayer_audio_stream_probe), player);
4493 gst_object_unref (pad);
4500 debug_error("There is no audio callback to configure.\n");
4510 __mmplayer_init_factories(mm_player_t* player) // @
4514 return_if_fail ( player );
4516 #ifdef GST_API_VERSION_1
4517 player->factories = gst_registry_feature_filter(gst_registry_get(),
4518 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
4520 player->factories = gst_registry_feature_filter(gst_registry_get_default(),
4521 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
4524 player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
4530 __mmplayer_release_factories(mm_player_t* player) // @
4534 return_if_fail ( player );
4536 if (player->factories)
4538 gst_plugin_feature_list_free (player->factories);
4539 player->factories = NULL;
4546 __mmplayer_release_misc(mm_player_t* player)
4551 return_if_fail ( player );
4553 player->use_video_stream = FALSE;
4554 player->video_stream_cb = NULL;
4555 player->video_stream_cb_user_param = NULL;
4557 player->audio_stream_cb = NULL;
4558 player->audio_stream_cb_user_param = NULL;
4560 player->audio_buffer_cb = NULL;
4561 player->audio_buffer_cb_user_param = NULL;
4563 player->sent_bos = FALSE;
4564 player->playback_rate = DEFAULT_PLAYBACK_RATE;
4566 player->doing_seek = FALSE;
4568 player->streamer = NULL;
4569 player->updated_bitrate_count = 0;
4570 player->total_bitrate = 0;
4571 player->updated_maximum_bitrate_count = 0;
4572 player->total_maximum_bitrate = 0;
4574 player->not_found_demuxer = 0;
4576 player->last_position = 0;
4577 player->duration = 0;
4578 player->http_content_size = 0;
4579 player->not_supported_codec = MISSING_PLUGIN_NONE;
4580 player->can_support_codec = FOUND_PLUGIN_NONE;
4581 player->pending_seek.is_pending = FALSE;
4582 player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
4583 player->pending_seek.pos = 0;
4584 player->msg_posted = FALSE;
4585 player->has_many_types = FALSE;
4587 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
4589 player->bitrate[i] = 0;
4590 player->maximum_bitrate[i] = 0;
4593 /* clean found parsers */
4594 if (player->parsers)
4596 g_list_free(player->parsers);
4597 player->parsers = NULL;
4600 MMPLAYER_FREEIF(player->album_art);
4602 /* free memory related to audio effect */
4603 if(player->audio_effect_info.custom_ext_level_for_plugin)
4605 free(player->audio_effect_info.custom_ext_level_for_plugin);
4611 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
4613 GstElement *element = NULL;
4616 debug_log("creating %s to plug\n", name);
4618 element = gst_element_factory_make(name, NULL);
4621 debug_error("failed to create queue\n");
4625 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
4627 debug_error("failed to set state READY to %s\n", name);
4631 if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
4633 debug_error("failed to add %s\n", name);
4637 sinkpad = gst_element_get_static_pad(element, "sink");
4639 if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
4641 debug_error("failed to link %s\n", name);
4642 gst_object_unref (sinkpad);
4647 debug_log("linked %s to pipeline successfully\n", name);
4649 gst_object_unref (sinkpad);
4655 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
4656 const char *padname, const GList *templlist)
4659 gboolean has_dynamic_pads = FALSE;
4660 gboolean has_many_types = FALSE;
4661 const char *klass = NULL;
4662 GstStaticPadTemplate *padtemplate = NULL;
4663 GstElementFactory *factory = NULL;
4664 GstElement* queue = NULL;
4665 GstElement* parser = NULL;
4666 GstPad *pssrcpad = NULL;
4667 GstPad *qsrcpad = NULL, *qsinkpad = NULL;
4668 MMPlayerGstElement *mainbin = NULL;
4669 GstStructure* str = NULL;
4670 GstCaps* srccaps = NULL;
4671 GstState warmup = GST_STATE_READY;
4672 gboolean isvideo_decoder = FALSE;
4673 guint q_max_size_time = 0;
4677 return_val_if_fail ( player &&
4679 player->pipeline->mainbin,
4682 mainbin = player->pipeline->mainbin;
4684 debug_log("plugging pad %s:%s to newly create %s:%s\n",
4685 GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
4686 GST_PAD_NAME( srcpad ),
4687 GST_ELEMENT_NAME( sinkelement ),
4690 factory = gst_element_get_factory(sinkelement);
4691 klass = gst_element_factory_get_klass(factory);
4693 /* check if player can do start continually */
4694 MMPLAYER_CHECK_CMD_IF_EXIT(player);
4696 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, warmup) )
4698 if (isvideo_decoder)
4699 player->keep_detecting_vcodec = TRUE;
4701 debug_error("failed to set %d state to %s\n", warmup, GST_ELEMENT_NAME( sinkelement ));
4705 /* add to pipeline */
4706 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
4708 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
4712 debug_log("element klass : %s\n", klass);
4714 /* added to support multi track files */
4715 /* only decoder case and any of the video/audio still need to link*/
4716 if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
4720 name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
4722 if (g_strrstr(name, "mpegtsdemux"))
4724 gchar *demux_caps = NULL;
4725 gchar *parser_name = NULL;
4726 GstCaps *dcaps = NULL;
4728 #ifdef GST_API_VERSION_1
4729 dcaps = gst_pad_get_current_caps(srcpad);
4731 dcaps = gst_pad_get_caps(srcpad);
4733 demux_caps = gst_caps_to_string(dcaps);
4735 if (g_strrstr(demux_caps, "video/x-h264"))
4737 parser_name = g_strdup("h264parse");
4739 else if (g_strrstr(demux_caps, "video/mpeg"))
4741 parser_name = g_strdup("mpeg4videoparse");
4744 gst_caps_unref(dcaps);
4745 MMPLAYER_FREEIF( demux_caps );
4749 parser = __mmplayer_element_create_and_link(player, srcpad, parser_name);
4751 MMPLAYER_FREEIF(parser_name);
4755 debug_error("failed to create parser\n");
4759 /* update srcpad if parser is created */
4760 pssrcpad = gst_element_get_static_pad(parser, "src");
4765 MMPLAYER_FREEIF(name);
4767 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
4770 debug_error("failed to create queue\n");
4774 /* update srcpad to link with decoder */
4775 qsrcpad = gst_element_get_static_pad(queue, "src");
4778 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
4780 /* assigning queue handle for futher manipulation purpose */
4781 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
4782 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
4784 mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
4785 mainbin[MMPLAYER_M_Q1].gst = queue;
4787 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
4789 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
4791 mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
4792 mainbin[MMPLAYER_M_Q2].gst = queue;
4794 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
4798 debug_critical("Not supporting more then two elementary stream\n");
4802 pad = gst_element_get_static_pad(sinkelement, padname);
4806 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
4807 padname, GST_ELEMENT_NAME(sinkelement) );
4809 pad = gst_element_get_static_pad(sinkelement, "sink");
4812 debug_error("failed to get pad(sink) from %s. \n",
4813 GST_ELEMENT_NAME(sinkelement) );
4818 /* to check the video/audio type set the proper flag*/
4820 #ifdef GST_API_VERSION_1
4821 srccaps = gst_pad_get_current_caps( srcpad );
4823 srccaps = gst_pad_get_caps( srcpad );
4828 str = gst_caps_get_structure( srccaps, 0 );
4832 name = gst_structure_get_name(str);
4837 /* link queue and decoder. so, it will be queue - decoder. */
4838 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
4840 gst_object_unref(GST_OBJECT(pad));
4841 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
4843 /* reconstitute supportable codec */
4844 if (strstr(name, "video"))
4846 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
4848 else if (strstr(name, "audio"))
4850 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
4855 if (strstr(name, "video"))
4857 player->videodec_linked = 1;
4858 debug_msg("player->videodec_linked set to 1\n");
4861 else if (strstr(name, "audio"))
4863 player->audiodec_linked = 1;
4864 debug_msg("player->auddiodec_linked set to 1\n");
4867 gst_object_unref(GST_OBJECT(pad));
4868 gst_caps_unref(GST_CAPS(srccaps));
4872 if ( !MMPLAYER_IS_HTTP_PD(player) )
4874 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
4876 if (MMPLAYER_IS_HTTP_STREAMING(player))
4878 #ifndef GST_API_VERSION_1
4879 GstFormat fmt = GST_FORMAT_BYTES;
4881 gint64 dur_bytes = 0L;
4882 gchar *file_buffering_path = NULL;
4883 gboolean use_file_buffer = FALSE;
4885 if ( !mainbin[MMPLAYER_M_S_BUFFER].gst)
4887 debug_log("creating http streaming buffering queue\n");
4889 queue = gst_element_factory_make("queue2", "http_streaming_buffer");
4892 debug_critical ( "failed to create buffering queue element\n" );
4896 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
4898 debug_error("failed to set state READY to buffering queue\n");
4902 if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
4904 debug_error("failed to add buffering queue\n");
4908 qsinkpad = gst_element_get_static_pad(queue, "sink");
4909 qsrcpad = gst_element_get_static_pad(queue, "src");
4911 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
4913 debug_error("failed to link buffering queue\n");
4919 mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
4920 mainbin[MMPLAYER_M_S_BUFFER].gst = queue;
4922 if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
4924 #ifdef GST_API_VERSION_1
4925 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
4926 debug_error("fail to get duration.\n");
4928 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
4929 debug_error("fail to get duration.\n");
4934 use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
4935 file_buffering_path = g_strdup(PLAYER_INI()->http_file_buffer_path);
4939 __mm_player_streaming_set_buffer(player->streamer,
4942 PLAYER_INI()->http_max_size_bytes,
4944 PLAYER_INI()->http_buffering_limit,
4945 PLAYER_INI()->http_buffering_time,
4947 file_buffering_path,
4950 MMPLAYER_FREEIF(file_buffering_path);
4955 /* if it is not decoder or */
4956 /* in decoder case any of the video/audio still need to link*/
4957 if(!g_strrstr(klass, "Decoder"))
4960 pad = gst_element_get_static_pad(sinkelement, padname);
4963 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
4964 padname, GST_ELEMENT_NAME(sinkelement) );
4966 pad = gst_element_get_static_pad(sinkelement, "sink");
4970 debug_error("failed to get pad(sink) from %s. \n",
4971 GST_ELEMENT_NAME(sinkelement) );
4976 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
4978 gst_object_unref(GST_OBJECT(pad));
4979 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
4983 gst_object_unref(GST_OBJECT(pad));
4986 for(;templlist != NULL; templlist = templlist->next)
4988 padtemplate = templlist->data;
4990 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
4992 if( padtemplate->direction != GST_PAD_SRC ||
4993 padtemplate->presence == GST_PAD_REQUEST )
4996 switch(padtemplate->presence)
4998 case GST_PAD_ALWAYS:
5000 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
5001 #ifdef GST_API_VERSION_1
5002 GstCaps *caps = gst_pad_get_current_caps(srcpad);
5004 GstCaps *caps = gst_pad_get_caps(srcpad);
5007 /* Check whether caps has many types */
5008 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser")) {
5009 debug_log ("has_many_types for this caps [%s]\n", gst_caps_to_string(caps));
5010 has_many_types = TRUE;
5014 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
5016 gst_object_unref(GST_OBJECT(srcpad));
5017 gst_caps_unref(GST_CAPS(caps));
5019 debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
5023 gst_caps_unref(GST_CAPS(caps));
5024 gst_object_unref(GST_OBJECT(srcpad));
5030 case GST_PAD_SOMETIMES:
5031 has_dynamic_pads = TRUE;
5039 /* check if player can do start continually */
5040 MMPLAYER_CHECK_CMD_IF_EXIT(player);
5042 if( has_dynamic_pads )
5044 player->have_dynamic_pad = TRUE;
5045 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, "pad-added",
5046 G_CALLBACK(__mmplayer_add_new_pad), player);
5048 /* for streaming, more then one typefind will used for each elementary stream
5049 * so this doesn't mean the whole pipeline completion
5051 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
5053 MMPLAYER_SIGNAL_CONNECT( player, sinkelement, "no-more-pads",
5054 G_CALLBACK(__mmplayer_pipeline_complete), player);
5062 player->has_many_types = has_many_types;
5064 pad = gst_element_get_static_pad(sinkelement, "src");
5065 MMPLAYER_SIGNAL_CONNECT (player, pad, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
5066 gst_object_unref (GST_OBJECT(pad));
5070 /* check if player can do start continually */
5071 MMPLAYER_CHECK_CMD_IF_EXIT(player);
5073 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
5075 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
5081 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
5083 debug_error("failed to set state PAUSED to queue\n");
5089 gst_object_unref (GST_OBJECT(qsrcpad));
5095 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
5097 debug_error("failed to set state PAUSED to queue\n");
5103 gst_object_unref (GST_OBJECT(pssrcpad));
5115 gst_object_unref(GST_OBJECT(qsrcpad));
5117 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
5118 * You need to explicitly set elements to the NULL state before
5119 * dropping the final reference, to allow them to clean up.
5121 gst_element_set_state(queue, GST_STATE_NULL);
5122 /* And, it still has a parent "player".
5123 * You need to let the parent manage the object instead of unreffing the object directly.
5126 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
5127 //gst_object_unref( queue );
5131 gst_caps_unref(GST_CAPS(srccaps));
5136 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
5139 //const gchar *name;
5141 /* we only care about element factories */
5142 if (!GST_IS_ELEMENT_FACTORY(feature))
5145 /* only parsers, demuxers and decoders */
5146 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
5147 //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
5149 if( g_strrstr(klass, "Demux") == NULL &&
5150 g_strrstr(klass, "Codec/Decoder") == NULL &&
5151 g_strrstr(klass, "Depayloader") == NULL &&
5152 g_strrstr(klass, "Parse") == NULL)
5160 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
5162 mm_player_t* player = (mm_player_t*) data;
5163 GstCaps *caps = NULL;
5164 GstStructure *str = NULL;
5169 return_if_fail ( pad )
5170 return_if_fail ( unused )
5171 return_if_fail ( data )
5173 #ifdef GST_API_VERSION_1
5174 caps = gst_pad_get_current_caps(pad);
5176 caps = gst_pad_get_caps(pad);
5181 str = gst_caps_get_structure(caps, 0);
5185 name = gst_structure_get_name(str);
5188 debug_log("name=%s\n", name);
5190 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
5192 debug_error("failed to autoplug for type (%s)\n", name);
5193 gst_caps_unref(caps);
5197 gst_caps_unref(caps);
5199 __mmplayer_pipeline_complete( NULL, (gpointer)player );
5206 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
5210 const char *stream_type;
5211 gchar *version_field = NULL;
5215 return_if_fail ( player );
5216 return_if_fail ( caps );
5218 str = gst_caps_get_structure(caps, 0);
5222 stream_type = gst_structure_get_name(str);
5227 /* set unlinked mime type for downloadable codec */
5228 if (g_str_has_prefix(stream_type, "video/"))
5230 if (g_str_has_prefix(stream_type, "video/mpeg"))
5232 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
5233 version_field = MM_PLAYER_MPEG_VNAME;
5235 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
5237 gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
5238 version_field = MM_PLAYER_WMV_VNAME;
5241 else if (g_str_has_prefix(stream_type, "video/x-divx"))
5243 gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
5244 version_field = MM_PLAYER_DIVX_VNAME;
5249 player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
5253 player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
5256 else if (g_str_has_prefix(stream_type, "audio/"))
5258 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
5260 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
5261 version_field = MM_PLAYER_MPEG_VNAME;
5263 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
5265 gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
5266 version_field = MM_PLAYER_WMA_VNAME;
5271 player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
5275 player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
5282 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
5284 mm_player_t* player = (mm_player_t*) data;
5285 GstCaps *caps = NULL;
5286 GstStructure *str = NULL;
5290 return_if_fail ( player );
5291 return_if_fail ( pad );
5293 GST_OBJECT_LOCK (pad);
5294 #ifdef GST_API_VERSION_1
5295 if ((caps = gst_pad_get_current_caps (pad)))
5298 if ((caps = GST_PAD_CAPS(pad)))
5301 GST_OBJECT_UNLOCK (pad);
5305 #ifdef GST_API_VERSION_1
5306 caps = gst_pad_get_current_caps(pad);
5308 caps = gst_pad_get_caps(pad);
5310 if ( !caps ) return;
5313 //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5315 str = gst_caps_get_structure(caps, 0);
5319 name = gst_structure_get_name(str);
5323 player->num_dynamic_pad++;
5324 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
5326 /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
5327 * If want to play it, remove this code.
5329 if (g_strrstr(name, "application"))
5331 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
5333 /* If id3/ape tag comes, keep going */
5334 debug_log("application mime exception : id3/ape tag");
5338 /* Otherwise, we assume that this stream is subtile. */
5339 debug_log(" application mime type pad is closed.");
5343 else if (g_strrstr(name, "audio"))
5345 gint samplerate = 0, channels = 0;
5347 /* set stream information */
5348 /* if possible, set it here because the caps is not distrubed by resampler. */
5349 gst_structure_get_int (str, "rate", &samplerate);
5350 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
5352 gst_structure_get_int (str, "channels", &channels);
5353 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
5355 debug_log("audio samplerate : %d channels : %d", samplerate, channels);
5357 else if (g_strrstr(name, "video"))
5360 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
5362 /* don't make video because of not required */
5363 if (stype == MM_DISPLAY_SURFACE_NULL)
5365 debug_log("no video because it's not required");
5369 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
5372 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
5374 debug_error("failed to autoplug for type (%s)", name);
5376 __mmplayer_set_unlinked_mime_type(player, caps);
5379 gst_caps_unref(caps);
5385 /* test API for tuning audio gain. this API should be
5386 * deprecated before the day of final release
5389 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
5391 mm_player_t* player = (mm_player_t*) hplayer;
5392 gint error = MM_ERROR_NONE;
5394 gboolean isMidi = FALSE;
5399 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5400 return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
5402 debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
5403 player->profile.play_mode, volume.level[0], volume.level[1]);
5405 isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
5412 /* is it proper volume level? */
5413 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
5415 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
5416 debug_log("Invalid Volume level!!!! \n");
5417 return MM_ERROR_INVALID_ARGUMENT;
5423 if ( player->pipeline->mainbin )
5425 GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
5427 if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
5429 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
5431 g_object_set(midi_element, "volume", volume.level[0], NULL);
5437 if ( player->pipeline->audiobin )
5439 GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
5441 /* Set to Avsysaudiosink element */
5445 gboolean mute = FALSE;
5446 vol_value = volume.level[0];
5448 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
5450 mute = (vol_value == 0)? TRUE:FALSE;
5452 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
5464 __mmplayer_can_extract_pcm( mm_player_t* player )
5466 MMHandleType attrs = 0;
5467 gboolean is_drm = FALSE;
5468 gboolean sound_extraction = FALSE;
5470 return_val_if_fail ( player, FALSE );
5472 attrs = MMPLAYER_GET_ATTRS(player);
5475 debug_error("fail to get attributes.");
5479 /* check file is drm or not */
5480 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
5482 /* get sound_extraction property */
5483 mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
5485 if ( ! sound_extraction || is_drm )
5487 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
5495 __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms )
5499 return_if_fail( player );
5501 /* cancel if existing */
5502 __mmplayer_cancel_delayed_eos( player );
5505 /* post now if delay is zero */
5506 if ( delay_in_ms == 0 || player->is_sound_extraction)
5508 debug_log("eos delay is zero. posting EOS now\n");
5509 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
5511 if ( player->is_sound_extraction )
5512 __mmplayer_cancel_delayed_eos(player);
5517 /* init new timeout */
5518 /* NOTE : consider give high priority to this timer */
5520 debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
5521 player->eos_timer = g_timeout_add( delay_in_ms,
5522 __mmplayer_eos_timer_cb, player );
5525 /* check timer is valid. if not, send EOS now */
5526 if ( player->eos_timer == 0 )
5528 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
5529 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
5537 __mmplayer_eos_timer_cb(gpointer u_data)
5539 mm_player_t* player = NULL;
5540 player = (mm_player_t*) u_data;
5544 return_val_if_fail( player, FALSE );
5547 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
5549 /* cleare timer id */
5550 player->eos_timer = 0;
5554 /* we are returning FALSE as we need only one posting */
5558 void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
5560 gint antishock = FALSE;
5561 MMHandleType attrs = 0;
5565 return_if_fail ( player && player->pipeline );
5567 /* It should be passed for video only clip */
5568 if ( ! player->pipeline->audiobin )
5571 if ( ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink")) )
5573 attrs = MMPLAYER_GET_ATTRS(player);
5576 debug_error("fail to get attributes.\n");
5580 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
5582 debug_log("setting antishock as (%d)\n", antishock);
5584 if ( disable_by_force )
5586 debug_log("but, antishock is disabled by force when is seeked\n");
5591 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
5599 /* Note : if silent is true, then subtitle would not be displayed. :*/
5600 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
5602 mm_player_t* player = (mm_player_t*) hplayer;
5606 /* check player handle */
5607 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5609 player->is_subtitle_off = silent;
5611 debug_log("subtitle is %s.\n", player->is_subtitle_off ? "ON" : "OFF");
5615 return MM_ERROR_NONE;
5619 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
5621 mm_player_t* player = (mm_player_t*) hplayer;
5625 /* check player handle */
5626 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5628 *silent = player->is_subtitle_off;
5630 debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
5634 return MM_ERROR_NONE;
5637 int _mmplayer_get_track_count(MMHandleType hplayer, MMPlayerTrackType track_type, int *count)
5639 mm_player_t* player = (mm_player_t*) hplayer;
5640 MMHandleType attrs = 0;
5641 int ret = MM_ERROR_NONE;
5645 /* check player handle */
5646 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5647 return_val_if_fail(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
5648 return_val_if_fail((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
5649 ||(MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING),
5650 MM_ERROR_PLAYER_INVALID_STATE);
5652 attrs = MMPLAYER_GET_ATTRS(player);
5655 debug_error("cannot get content attribute");
5656 return MM_ERROR_PLAYER_INTERNAL;
5661 case MM_PLAYER_TRACK_TYPE_AUDIO:
5662 ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
5664 case MM_PLAYER_TRACK_TYPE_VIDEO:
5665 ret = mm_attrs_get_int_by_name(attrs, "content_video_track_num", count);
5667 case MM_PLAYER_TRACK_TYPE_TEXT:
5668 ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
5671 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
5675 debug_log ("%d track num is %d\n", track_type, *count);
5683 __get_state_name ( int state )
5687 case MM_PLAYER_STATE_NULL:
5689 case MM_PLAYER_STATE_READY:
5691 case MM_PLAYER_STATE_PAUSED:
5693 case MM_PLAYER_STATE_PLAYING:
5695 case MM_PLAYER_STATE_NONE: