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 gboolean __mmplayer_set_state(mm_player_t* player, int state);
115 static int __mmplayer_get_state(mm_player_t* player);
116 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
117 static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data);
118 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
119 static gboolean __mmplayer_is_amr_type (gchar *str_caps);
120 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
122 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
123 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
124 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
126 static gboolean __mmplayer_get_stream_service_type( mm_player_t* player );
127 static void __mmplayer_init_factories(mm_player_t* player);
128 static void __mmplayer_release_factories(mm_player_t* player);
129 static void __mmplayer_release_misc(mm_player_t* player);
130 static gboolean __mmplayer_gstreamer_init(void);
132 gboolean __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param);
134 int __mmplayer_switch_audio_sink (mm_player_t* player);
135 static int __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
136 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
137 static void __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms );
138 static void __mmplayer_cancel_delayed_eos( mm_player_t* player );
139 static int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime);
140 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
141 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
142 static gpointer __mmplayer_repeat_thread(gpointer data);
143 int _mmplayer_get_track_count(MMHandleType hplayer, MMPlayerTrackType track_type, int *count);
144 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
145 static void __gst_set_async_state_change(mm_player_t* player, gboolean async);
146 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
147 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
150 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
151 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
153 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
154 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
157 const gchar * __get_state_name ( int state );
159 static gboolean __mmplayer_warm_up_video_codec( mm_player_t* player, GstElementFactory *factory);
161 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
162 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
163 static int __mmplayer_start_streaming_ext(mm_player_t *player);
164 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
167 /*===========================================================================================
169 | FUNCTION DEFINITIONS |
171 ========================================================================================== */
173 /* implementing player FSM */
174 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
176 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
178 MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
179 MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
180 MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
181 MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
185 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
187 //debug_log("incomming command : %d \n", command );
189 current_state = MMPLAYER_CURRENT_STATE(player);
190 pending_state = MMPLAYER_PENDING_STATE(player);
191 target_state = MMPLAYER_TARGET_STATE(player);
192 prev_state = MMPLAYER_PREV_STATE(player);
194 MMPLAYER_PRINT_STATE(player);
198 case MMPLAYER_COMMAND_CREATE:
200 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
202 if ( current_state == MM_PLAYER_STATE_NULL ||
203 current_state == MM_PLAYER_STATE_READY ||
204 current_state == MM_PLAYER_STATE_PAUSED ||
205 current_state == MM_PLAYER_STATE_PLAYING )
210 case MMPLAYER_COMMAND_DESTROY:
212 /* destroy can called anytime */
214 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
218 case MMPLAYER_COMMAND_REALIZE:
220 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
222 if ( pending_state != MM_PLAYER_STATE_NONE )
228 /* need ready state to realize */
229 if ( current_state == MM_PLAYER_STATE_READY )
232 if ( current_state != MM_PLAYER_STATE_NULL )
238 case MMPLAYER_COMMAND_UNREALIZE:
240 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
242 if ( current_state == MM_PLAYER_STATE_NULL )
247 case MMPLAYER_COMMAND_START:
249 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
251 if ( pending_state == MM_PLAYER_STATE_NONE )
253 if ( current_state == MM_PLAYER_STATE_PLAYING )
255 else if ( current_state != MM_PLAYER_STATE_READY &&
256 current_state != MM_PLAYER_STATE_PAUSED )
259 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
263 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
265 debug_log("player is going to paused state, just change the pending state as playing");
274 case MMPLAYER_COMMAND_STOP:
276 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
278 if ( current_state == MM_PLAYER_STATE_READY )
281 /* need playing/paused state to stop */
282 if ( current_state != MM_PLAYER_STATE_PLAYING &&
283 current_state != MM_PLAYER_STATE_PAUSED )
288 case MMPLAYER_COMMAND_PAUSE:
290 if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
293 if (player->doing_seek)
294 goto NOT_COMPLETED_SEEK;
296 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
298 if ( pending_state == MM_PLAYER_STATE_NONE )
300 if ( current_state == MM_PLAYER_STATE_PAUSED )
302 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
305 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
309 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
311 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
312 debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
320 case MMPLAYER_COMMAND_RESUME:
322 if ( MMPLAYER_IS_LIVE_STREAMING(player) )
325 if (player->doing_seek)
326 goto NOT_COMPLETED_SEEK;
328 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
330 if ( pending_state == MM_PLAYER_STATE_NONE )
332 if ( current_state == MM_PLAYER_STATE_PLAYING )
334 else if ( current_state != MM_PLAYER_STATE_PAUSED )
337 else if ( pending_state == MM_PLAYER_STATE_PLAYING )
341 else if ( pending_state == MM_PLAYER_STATE_PAUSED )
343 debug_log("player is going to paused state, just change the pending state as playing");
355 player->cmd = command;
358 return MM_ERROR_NONE;
361 debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
362 MMPLAYER_STATE_GET_NAME(current_state), command);
363 return MM_ERROR_PLAYER_INVALID_STATE;
366 debug_warning("not completed seek");
367 return MM_ERROR_PLAYER_DOING_SEEK;
370 debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
371 return MM_ERROR_PLAYER_NO_OP;
374 debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
375 return MM_ERROR_PLAYER_NO_OP;
379 __mmplayer_videostream_cb(GstElement *element, void *stream,
380 int width, int height, gpointer data) // @
382 mm_player_t* player = (mm_player_t*)data;
385 return_if_fail ( player );
389 if (player->video_stream_cb )
391 length = width * height * 4; // for rgb 32bit
392 player->video_stream_cb(stream, length, player->video_stream_cb_user_param, width, height);
399 __mmplayer_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer data)
401 mm_player_t* player = (mm_player_t*)data;
403 return_if_fail ( player );
407 if (player->video_frame_render_error_cb )
411 int surface_type = 0;
412 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
413 switch (surface_type)
415 case MM_DISPLAY_SURFACE_X_EXT:
416 player->video_frame_render_error_cb((unsigned int*)error_id, player->video_frame_render_error_cb_user_param);
417 debug_log("display surface type(X_EXT) : render error callback(%p) is finished", player->video_frame_render_error_cb);
420 debug_error("video_frame_render_error_cb was set, but this surface type(%d) is not supported", surface_type);
426 debug_error("could not get surface type");
431 debug_warning("video_frame_render_error_cb was not set");
437 /* This function should be called after the pipeline goes PAUSED or higher
440 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) // @
442 static gboolean has_duration = FALSE;
443 static gboolean has_video_attrs = FALSE;
444 static gboolean has_audio_attrs = FALSE;
445 static gboolean has_bitrate = FALSE;
446 gboolean missing_only = FALSE;
447 gboolean all = FALSE;
449 #ifndef GST_API_VERSION_1
450 GstFormat fmt = GST_FORMAT_TIME;
453 GstStructure* p = NULL;
454 MMHandleType attrs = 0;
456 gint stream_service_type = STREAMING_SERVICE_NONE;
461 return_val_if_fail ( player, FALSE );
463 /* check player state here */
464 if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
465 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING )
467 /* give warning now only */
468 debug_warning("be careful. content attributes may not available in this state ");
471 /* get content attribute first */
472 attrs = MMPLAYER_GET_ATTRS(player);
475 debug_error("cannot get content attribute");
479 /* get update flag */
481 if ( flag & ATTR_MISSING_ONLY )
484 debug_log("updating missed attr only");
487 if ( flag & ATTR_ALL )
490 has_duration = FALSE;
491 has_video_attrs = FALSE;
492 has_audio_attrs = FALSE;
495 debug_log("updating all attrs");
498 if ( missing_only && all )
500 debug_warning("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
501 missing_only = FALSE;
504 if ( (flag & ATTR_DURATION) || (!has_duration && missing_only) || all )
506 debug_log("try to update duration");
507 has_duration = FALSE;
509 #ifdef GST_API_VERSION_1
510 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec ))
512 player->duration = dur_nsec;
513 debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
516 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
518 player->duration = dur_nsec;
519 debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
523 /* try to get streaming service type */
524 stream_service_type = __mmplayer_get_stream_service_type( player );
525 mm_attrs_set_int_by_name ( attrs, "streaming_type", stream_service_type );
527 /* check duration is OK */
528 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
530 debug_error("not ready to get duration");
535 mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
537 debug_log("duration updated");
541 if ( (flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all )
543 /* update audio params
544 NOTE : We need original audio params and it can be only obtained from src pad of audio
545 decoder. Below code only valid when we are not using 'resampler' just before
548 debug_log("try to update audio attrs");
549 has_audio_attrs = FALSE;
551 if ( player->pipeline->audiobin &&
552 player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
554 GstCaps *caps_a = NULL;
556 gint samplerate = 0, channels = 0;
558 pad = gst_element_get_static_pad(
559 player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
563 #ifdef GST_API_VERSION_1
564 caps_a = gst_pad_get_current_caps( pad );
566 caps_a = gst_pad_get_negotiated_caps( pad );
571 p = gst_caps_get_structure (caps_a, 0);
573 mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
575 gst_structure_get_int (p, "rate", &samplerate);
576 mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
578 gst_structure_get_int (p, "channels", &channels);
579 mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
581 debug_log("samplerate : %d channels : %d", samplerate, channels);
583 gst_caps_unref( caps_a );
586 has_audio_attrs = TRUE;
590 debug_warning("not ready to get audio caps");
593 gst_object_unref( pad );
597 debug_warning("failed to get pad from audiosink");
602 if ( (flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all )
604 debug_log("try to update video attrs");
605 has_video_attrs = FALSE;
607 if ( player->pipeline->videobin &&
608 player->pipeline->videobin[MMPLAYER_V_SINK].gst )
610 GstCaps *caps_v = NULL;
615 pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
618 #ifdef GST_API_VERSION_1
619 caps_v = gst_pad_get_current_caps( pad );
621 caps_v = gst_pad_get_negotiated_caps( pad );
625 p = gst_caps_get_structure (caps_v, 0);
626 gst_structure_get_int (p, "width", &width);
627 mm_attrs_set_int_by_name(attrs, "content_video_width", width);
629 gst_structure_get_int (p, "height", &height);
630 mm_attrs_set_int_by_name(attrs, "content_video_height", height);
632 gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
634 debug_log("width : %d height : %d", width, height );
636 gst_caps_unref( caps_v );
641 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
642 debug_log("fps : %d", tmpNu / tmpDe);
645 has_video_attrs = TRUE;
649 debug_log("no negitiated caps from videosink");
651 gst_object_unref( pad );
656 debug_log("no videosink sink pad");
662 if ( (flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all )
664 debug_log("try to update bitrate");
667 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
668 if (player->duration)
670 guint64 data_size = 0;
672 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
674 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
676 if (stat(path, &sb) == 0)
678 data_size = (guint64)sb.st_size;
681 else if (MMPLAYER_IS_HTTP_STREAMING(player))
683 data_size = player->http_content_size;
689 guint64 msec_dur = 0;
691 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
692 bitrate = data_size * 8 * 1000 / msec_dur;
693 debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
694 mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
702 if ( mmf_attrs_commit ( attrs ) )
704 debug_error("failed to update attributes\n");
712 gint __mmplayer_get_stream_service_type( mm_player_t* player )
714 gint streaming_type = STREAMING_SERVICE_NONE;
718 return_val_if_fail ( player &&
720 player->pipeline->mainbin &&
721 player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
724 /* streaming service type if streaming */
725 if ( ! MMPLAYER_IS_STREAMING(player) )
727 debug_log("not a streamming");
728 return STREAMING_SERVICE_NONE;
731 if (MMPLAYER_IS_RTSP_STREAMING(player))
733 /* get property from rtspsrc element */
734 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst),
735 "service_type", &streaming_type, NULL);
737 else if (MMPLAYER_IS_HTTP_STREAMING(player))
739 streaming_type = player->duration == 0 ?
740 STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
743 switch ( streaming_type )
745 case STREAMING_SERVICE_LIVE:
746 debug_log("it's live streaming");
748 case STREAMING_SERVICE_VOD:
749 debug_log("it's vod streaming");
751 case STREAMING_SERVICE_NONE:
752 debug_error("should not get here");
755 debug_error("should not get here");
758 player->streaming_type = streaming_type;
761 return streaming_type;
765 /* this function sets the player state and also report
766 * it to applicaton by calling callback function
769 __mmplayer_set_state(mm_player_t* player, int state) // @
771 MMMessageParamType msg = {0, };
772 int asm_result = MM_ERROR_NONE;
773 gboolean post_bos = FALSE;
774 gboolean interrupted_by_asm = FALSE;
777 return_val_if_fail ( player, FALSE );
779 if ( MMPLAYER_CURRENT_STATE(player) == state )
781 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
782 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
786 /* update player states */
787 MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
788 MMPLAYER_CURRENT_STATE(player) = state;
790 /* FIXIT : it's better to do like below code
791 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_TARGET_STATE(player) )
792 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
793 and add more code to handling PENDING_STATE.
795 if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
796 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
799 MMPLAYER_PRINT_STATE(player);
801 /* do some FSM stuffs before posting new state to application */
802 interrupted_by_asm = player->sm.by_asm_cb;
804 switch ( MMPLAYER_CURRENT_STATE(player) )
806 case MM_PLAYER_STATE_NULL:
807 case MM_PLAYER_STATE_READY:
809 if (player->cmd == MMPLAYER_COMMAND_STOP)
811 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP);
812 if ( asm_result != MM_ERROR_NONE )
814 debug_error("failed to set asm state to stop\n");
821 case MM_PLAYER_STATE_PAUSED:
823 if ( ! player->sent_bos )
825 /* it's first time to update all content attrs. */
826 _mmplayer_update_content_attrs( player, ATTR_ALL );
829 /* add audio callback probe if condition is satisfied */
830 if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
832 __mmplayer_configure_audio_callback(player);
835 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE);
838 debug_error("failed to set asm state to PAUSE\n");
844 case MM_PLAYER_STATE_PLAYING:
846 /* try to get content metadata */
847 if ( ! player->sent_bos )
849 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
850 * c-api since c-api doesn't use _start() anymore. It may not work propery with
851 * legacy mmfw-player api */
852 _mmplayer_update_content_attrs( player, ATTR_MISSING_ONLY);
855 if ( player->cmd == MMPLAYER_COMMAND_START && !player->sent_bos )
857 __mmplayer_handle_missed_plugin ( player );
859 /* update video resource status */
860 if ( ( player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO )
862 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING);
865 MMMessageParamType msg = {0, };
867 debug_error("failed to go ahead because of video conflict\n");
869 msg.union_type = MM_MSG_UNION_CODE;
870 msg.code = MM_ERROR_POLICY_INTERRUPTED;
871 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
873 _mmplayer_unrealize((MMHandleType)player);
880 if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
882 /* initialize because auto resume is done well. */
883 player->resumed_by_rewind = FALSE;
884 player->playback_rate = 1.0;
887 if ( !player->sent_bos )
889 /* check audio codec field is set or not
890 * we can get it from typefinder or codec's caps.
892 gchar *audio_codec = NULL;
893 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
895 /* The codec format can't be sent for audio only case like amr, mid etc.
896 * Because, parser don't make related TAG.
897 * So, if it's not set yet, fill it with found data.
901 if ( g_strrstr(player->type, "audio/midi"))
903 audio_codec = g_strdup("MIDI");
906 else if ( g_strrstr(player->type, "audio/x-amr"))
908 audio_codec = g_strdup("AMR");
910 else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
912 audio_codec = g_strdup("AAC");
916 audio_codec = g_strdup("unknown");
918 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
920 MMPLAYER_FREEIF(audio_codec);
921 mmf_attrs_commit(player->attrs);
922 debug_log("set audio codec type with caps\n");
930 case MM_PLAYER_STATE_NONE:
932 debug_warning("invalid target state, there is nothing to do.\n");
937 /* post message to application */
938 if (MMPLAYER_TARGET_STATE(player) == state)
940 /* fill the message with state of player */
941 msg.state.previous = MMPLAYER_PREV_STATE(player);
942 msg.state.current = MMPLAYER_CURRENT_STATE(player);
944 /* state changed by asm callback */
945 if ( interrupted_by_asm )
947 msg.union_type = MM_MSG_UNION_CODE;
948 msg.code = player->sm.event_src;
949 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
951 /* state changed by usecase */
954 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
957 debug_log ("player reach the target state, then do something in each state(%s).\n",
958 MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
962 debug_log ("intermediate state, do nothing.\n");
963 MMPLAYER_PRINT_STATE(player);
969 MMTA_ACUM_ITEM_END("[KPI] start media player service", FALSE);
970 MMTA_ACUM_ITEM_END("[KPI] media player service create->playing", FALSE);
972 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
973 player->sent_bos = TRUE;
982 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
984 return_val_if_fail( player, FALSE );
988 if ( !player->msg_cb )
990 debug_warning("no msg callback. can't post msg now\n");
994 //debug_log("Message (type : %d) will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
996 player->msg_cb(msgtype, param, player->msg_cb_param);
1005 __mmplayer_get_state(mm_player_t* player) // @
1007 int state = MM_PLAYER_STATE_NONE;
1011 return_val_if_fail ( player, MM_PLAYER_STATE_NONE );
1013 state = MMPLAYER_CURRENT_STATE(player);
1015 debug_log("player state is %s.\n", MMPLAYER_STATE_GET_NAME(state));
1023 __gst_set_async_state_change(mm_player_t* player, gboolean async)
1026 return_if_fail( player && player->pipeline && player->pipeline->mainbin );
1028 /* need only when we are using decodebin */
1029 if ( ! PLAYER_INI()->use_decodebin )
1033 if ( player->pipeline->audiobin &&
1034 player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1036 debug_log("audiosink async : %d\n", async);
1037 g_object_set (G_OBJECT (player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "async", async, NULL);
1041 if ( player->pipeline->videobin &&
1042 player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1044 debug_log("videosink async : %d\n", async);
1045 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "async", async, NULL);
1048 /* decodebin if enabled */
1049 if ( PLAYER_INI()->use_decodebin )
1051 debug_log("decodebin async : %d\n", async);
1052 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst), "async-handling", async, NULL);
1058 static gpointer __mmplayer_repeat_thread(gpointer data)
1060 mm_player_t* player = (mm_player_t*) data;
1061 gboolean ret_value = FALSE;
1062 MMHandleType attrs = 0;
1065 return_val_if_fail ( player, NULL );
1067 while ( ! player->repeat_thread_exit )
1069 debug_log("repeat thread started. waiting for signal.\n");
1070 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1072 if ( player->repeat_thread_exit )
1074 debug_log("exiting repeat thread\n");
1078 if ( !player->cmd_lock )
1080 debug_log("can't get cmd lock\n");
1085 g_mutex_lock(player->cmd_lock);
1087 attrs = MMPLAYER_GET_ATTRS(player);
1089 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1091 debug_error("can not get play count\n");
1095 if ( player->section_repeat )
1097 ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1101 if ( player->playback_rate < 0.0 )
1103 player->resumed_by_rewind = TRUE;
1104 _mmplayer_set_mute((MMHandleType)player, 0);
1105 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1108 ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
1109 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1110 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1113 player->sent_bos = FALSE;
1118 debug_error("failed to set position to zero for rewind\n");
1122 /* decrease play count */
1125 /* we successeded to rewind. update play count and then wait for next EOS */
1128 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1130 /* commit attribute */
1131 if ( mmf_attrs_commit ( attrs ) )
1133 debug_error("failed to commit attribute\n");
1138 g_mutex_unlock(player->cmd_lock);
1145 __mmplayer_handle_buffering_message ( mm_player_t* player )
1147 MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1148 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1149 MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1150 MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1152 return_if_fail ( player );
1154 prev_state = MMPLAYER_PREV_STATE(player),
1155 current_state = MMPLAYER_CURRENT_STATE(player);
1156 target_state = MMPLAYER_TARGET_STATE(player);
1157 pending_state = MMPLAYER_PENDING_STATE(player);
1159 if ( MMPLAYER_IS_RTSP_STREAMING(player) )
1162 if ( !player->streamer->is_buffering )
1164 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1165 MMPLAYER_STATE_GET_NAME(prev_state),
1166 MMPLAYER_STATE_GET_NAME(current_state),
1167 MMPLAYER_STATE_GET_NAME(pending_state),
1168 MMPLAYER_STATE_GET_NAME(target_state));
1170 /* NOTE : if buffering has done, player has to go to target state. */
1171 switch ( target_state )
1173 case MM_PLAYER_STATE_PAUSED :
1175 switch ( pending_state )
1177 case MM_PLAYER_STATE_PLAYING:
1179 __gst_pause ( player, TRUE );
1183 case MM_PLAYER_STATE_PAUSED:
1185 debug_log("player is already going to paused state, there is nothing to do.\n");
1189 case MM_PLAYER_STATE_NONE:
1190 case MM_PLAYER_STATE_NULL:
1191 case MM_PLAYER_STATE_READY:
1194 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1201 case MM_PLAYER_STATE_PLAYING :
1203 switch ( pending_state )
1205 case MM_PLAYER_STATE_NONE:
1207 if (current_state != MM_PLAYER_STATE_PLAYING)
1208 __gst_resume ( player, TRUE );
1212 case MM_PLAYER_STATE_PAUSED:
1214 /* NOTE: It should be worked as asynchronously.
1215 * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1217 __gst_resume ( player, TRUE );
1221 case MM_PLAYER_STATE_PLAYING:
1223 debug_log("player is already going to playing state, there is nothing to do.\n");
1227 case MM_PLAYER_STATE_NULL:
1228 case MM_PLAYER_STATE_READY:
1231 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1238 case MM_PLAYER_STATE_NULL :
1239 case MM_PLAYER_STATE_READY :
1240 case MM_PLAYER_STATE_NONE :
1243 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1250 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1251 * it's for stopping the pipeline clock to prevent dropping the data in sink element.
1253 switch ( pending_state )
1255 case MM_PLAYER_STATE_NONE:
1257 if (current_state != MM_PLAYER_STATE_PAUSED)
1258 __gst_pause ( player, TRUE );
1262 case MM_PLAYER_STATE_PLAYING:
1264 __gst_pause ( player, TRUE );
1268 case MM_PLAYER_STATE_PAUSED:
1270 debug_log("player is already going to paused state, there is nothing to do.\n");
1274 case MM_PLAYER_STATE_NULL:
1275 case MM_PLAYER_STATE_READY:
1278 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1287 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
1289 int pro_value = 0; // in the case of expection, default will be returned.
1290 int dest_angle = rotation_angle;
1291 int rotation_using_type = -1;
1292 #define ROTATION_USING_X 0
1293 #define ROTATION_USING_FIMC 1
1294 #define ROTATION_USING_FLIP 2
1296 return_val_if_fail(player, FALSE);
1297 return_val_if_fail(value, FALSE);
1298 return_val_if_fail(rotation_angle >= 0, FALSE);
1300 if (rotation_angle >= 360)
1302 dest_angle = rotation_angle - 360;
1305 /* chech if supported or not */
1306 if ( dest_angle % 90 )
1308 debug_log("not supported rotation angle = %d", rotation_angle);
1312 if (player->use_video_stream)
1314 if (player->is_nv12_tiled)
1316 rotation_using_type = ROTATION_USING_FIMC;
1320 rotation_using_type = ROTATION_USING_FLIP;
1325 int surface_type = 0;
1326 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
1327 debug_log("check display surface type for rotation: %d", surface_type);
1329 switch (surface_type)
1331 case MM_DISPLAY_SURFACE_X:
1332 rotation_using_type = ROTATION_USING_X;
1334 case MM_DISPLAY_SURFACE_EVAS:
1335 if (player->is_nv12_tiled && !strcmp(PLAYER_INI()->videosink_element_evas,"evasimagesink"))
1337 rotation_using_type = ROTATION_USING_FIMC;
1339 else if (!player->is_nv12_tiled)
1341 rotation_using_type = ROTATION_USING_FLIP;
1345 debug_error("it should not be here..");
1350 rotation_using_type = ROTATION_USING_FLIP;
1355 debug_log("using %d type for rotation", rotation_using_type);
1357 /* get property value for setting */
1358 switch(rotation_using_type)
1360 case ROTATION_USING_X: // xvimagesink
1367 pro_value = 3; // clockwise 90
1373 pro_value = 1; // counter-clockwise 90
1378 case ROTATION_USING_FIMC: // fimcconvert
1385 pro_value = 90; // clockwise 90
1391 pro_value = 270; // counter-clockwise 90
1396 case ROTATION_USING_FLIP: // videoflip
1404 pro_value = 1; // clockwise 90
1410 pro_value = 3; // counter-clockwise 90
1417 debug_log("setting rotation property value : %d", pro_value);
1425 _mmplayer_update_video_param(mm_player_t* player) // @
1427 MMHandleType attrs = 0;
1428 int surface_type = 0;
1429 int org_angle = 0; // current supported angle values are 0, 90, 180, 270
1431 int user_angle_type= 0;
1432 int rotation_value = 0;
1436 /* check video sinkbin is created */
1437 return_val_if_fail ( player &&
1439 player->pipeline->videobin &&
1440 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
1441 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1442 MM_ERROR_PLAYER_NOT_INITIALIZED );
1444 attrs = MMPLAYER_GET_ATTRS(player);
1447 debug_error("cannot get content attribute");
1448 return MM_ERROR_PLAYER_INTERNAL;
1451 /* update user roation */
1452 mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
1454 /* get angle with user type */
1455 switch(user_angle_type)
1457 case MM_DISPLAY_ROTATION_NONE:
1460 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
1463 case MM_DISPLAY_ROTATION_180:
1466 case MM_DISPLAY_ROTATION_270: // clockwise 90
1471 /* get original orientation */
1472 if (player->v_stream_caps)
1474 GstStructure *str = NULL;
1476 str = gst_caps_get_structure (player->v_stream_caps, 0);
1477 if ( !gst_structure_get_int (str, "orientation", &org_angle))
1479 debug_log ("missing 'orientation' field in video caps");
1483 debug_log("origianl video orientation = %d", org_angle);
1487 debug_log("check user angle: %d, org angle: %d", user_angle, org_angle);
1489 /* get rotation value to set */
1490 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1492 /* check video stream callback is used */
1493 if( player->use_video_stream )
1495 if (player->is_nv12_tiled)
1497 gchar *ename = NULL;
1501 mm_attrs_get_int_by_name(attrs, "display_width", &width);
1502 mm_attrs_get_int_by_name(attrs, "display_height", &height);
1504 /* resize video frame with requested values for fimcconvert */
1505 #ifdef GST_API_VERSION_1
1506 ename = GST_OBJECT (gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1508 ename = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1511 if (g_strrstr(ename, "fimcconvert"))
1514 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1517 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1519 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
1520 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
1524 debug_error("no available video converter");
1525 return MM_ERROR_PLAYER_INTERNAL;
1530 debug_log("using video stream callback with memsink. player handle : [%p]", player);
1532 g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1535 return MM_ERROR_NONE;
1538 /* update display surface */
1539 mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
1540 debug_log("check display surface type attribute: %d", surface_type);
1542 /* configuring display */
1543 switch ( surface_type )
1545 case MM_DISPLAY_SURFACE_X:
1547 /* ximagesink or xvimagesink */
1550 int display_method = 0;
1555 int force_aspect_ratio = 0;
1556 gboolean visible = TRUE;
1558 /* common case if using x surface */
1559 mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
1562 #define GST_VAAPI_DISPLAY_TYPE_X11 1
1563 if (!strncmp(PLAYER_INI()->videosink_element_x,"vaapisink", strlen("vaapisink"))){
1564 debug_log("set video param: vaapisink display %d", GST_VAAPI_DISPLAY_TYPE_X11);
1565 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1566 "display", GST_VAAPI_DISPLAY_TYPE_X11,
1570 debug_log("set video param : xid %d", *(int*)xid);
1571 #ifdef GST_API_VERSION_1
1572 gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
1574 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
1579 /* FIXIT : is it error case? */
1580 debug_warning("still we don't have xid on player attribute. create it's own surface.");
1583 /* if xvimagesink */
1584 if (!strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
1586 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
1587 mm_attrs_get_int_by_name(attrs, "display_zoom", &zoom);
1588 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1589 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1590 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1591 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1592 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1593 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1595 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1596 "force-aspect-ratio", force_aspect_ratio,
1598 "rotate", rotation_value,
1599 "handle-events", TRUE,
1600 "display-geometry-method", display_method,
1601 "draw-borders", FALSE,
1609 debug_log("set video param : zoom %d", zoom);
1610 debug_log("set video param : rotate %d", rotation_value);
1611 debug_log("set video param : method %d", display_method);
1612 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1613 roi_x, roi_y, roi_w, roi_h );
1614 debug_log("set video param : visible %d", visible);
1615 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
1619 if (!strncmp(PLAYER_INI()->videosink_element_x, "vaapisink", strlen("vaapisink")))
1621 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1622 "rotation", rotation_value,
1624 debug_log("set video param: vaapisink rotation %d", rotation_value);
1628 case MM_DISPLAY_SURFACE_EVAS:
1630 void *object = NULL;
1632 gboolean visible = TRUE;
1634 /* common case if using evas surface */
1635 mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
1636 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1637 mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
1640 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1641 "evas-object", object,
1644 debug_log("set video param : evas-object %x", object);
1645 debug_log("set video param : visible %d", visible);
1649 debug_error("no evas object");
1650 return MM_ERROR_PLAYER_INTERNAL;
1653 /* if evasimagesink */
1654 if (!strcmp(PLAYER_INI()->videosink_element_evas,"evasimagesink") && player->is_nv12_tiled)
1658 int no_scaling = !scaling;
1660 mm_attrs_get_int_by_name(attrs, "display_width", &width);
1661 mm_attrs_get_int_by_name(attrs, "display_height", &height);
1663 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
1664 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
1668 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
1669 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
1670 "dst-width", 0, /* setting 0, output video width will be media src's width */
1671 "dst-height", 0, /* setting 0, output video height will be media src's height */
1676 /* scaling order to fimcconvert */
1679 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1683 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1685 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
1687 debug_log("set video param : display_evas_do_scaling %d", scaling);
1690 /* if evaspixmapsink */
1691 if (!strcmp(PLAYER_INI()->videosink_element_evas,"evaspixmapsink"))
1693 int display_method = 0;
1698 int origin_size = !scaling;
1700 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1701 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1702 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1703 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1704 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1706 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1707 "origin-size", origin_size,
1712 "display-geometry-method", display_method,
1715 debug_log("set video param : method %d", display_method);
1716 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1717 roi_x, roi_y, roi_w, roi_h );
1718 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
1720 g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1723 case MM_DISPLAY_SURFACE_X_EXT: /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
1725 void *pixmap_id_cb = NULL;
1726 void *pixmap_id_cb_user_data = NULL;
1727 int display_method = 0;
1728 gboolean visible = TRUE;
1730 /* if xvimagesink */
1731 if (strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
1733 debug_error("videosink is not xvimagesink");
1734 return MM_ERROR_PLAYER_INTERNAL;
1737 /* get information from attributes */
1738 mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
1739 mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
1740 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1744 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
1745 if (pixmap_id_cb_user_data)
1747 debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
1752 debug_error("failed to set pixmap-id-callback");
1753 return MM_ERROR_PLAYER_INTERNAL;
1755 debug_log("set video param : method %d", display_method);
1756 debug_log("set video param : visible %d", visible);
1758 /* set properties of videosink plugin */
1759 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1760 "display-geometry-method", display_method,
1761 "draw-borders", FALSE,
1763 "rotate", rotation_value,
1764 "pixmap-id-callback", pixmap_id_cb,
1765 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
1769 case MM_DISPLAY_SURFACE_NULL:
1778 return MM_ERROR_NONE;
1782 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
1784 mm_player_t* player = (mm_player_t*) u_data;
1788 #ifdef GST_API_VERSION_1
1790 gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1792 size = gst_buffer_get_size(buffer);
1794 if (player->audio_stream_cb && size && data)
1795 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
1797 gst_buffer_unmap (buffer, &info);
1799 data = GST_BUFFER_DATA(buffer);
1800 size = GST_BUFFER_SIZE(buffer);
1802 if (player->audio_stream_cb && size && data)
1803 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
1810 #ifdef GST_API_VERSION_1
1812 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
1814 mm_player_t* player = (mm_player_t*) data;
1815 MMMessageParamType msg = {0, };
1816 GstClockTime duration = 0;
1817 guint8 *text = NULL;
1818 gboolean ret = TRUE;
1823 return_val_if_fail ( player, FALSE );
1824 return_val_if_fail ( buffer, FALSE );
1826 gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1828 gst_buffer_unmap (buffer, &info);
1830 duration = GST_BUFFER_DURATION(buffer);
1832 if ( player->is_subtitle_off )
1834 debug_log("subtitle is OFF.\n" );
1840 debug_log("There is no subtitle to be displayed.\n" );
1844 msg.data = (void *) text;
1845 msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
1847 debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
1849 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
1857 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
1859 mm_player_t* player = (mm_player_t*) data;
1860 MMMessageParamType msg = {0, };
1861 GstClockTime duration = 0;
1862 guint8 *text = NULL;
1863 gboolean ret = TRUE;
1867 return_val_if_fail ( player, FALSE );
1868 return_val_if_fail ( buffer, FALSE );
1870 text = GST_BUFFER_DATA(buffer);
1871 duration = GST_BUFFER_DURATION(buffer);
1873 if ( player->is_subtitle_off )
1875 debug_log("subtitle is OFF.\n" );
1881 debug_log("There is no subtitle to be displayed.\n" );
1885 msg.data = (void *) text;
1886 msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
1888 debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
1890 MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
1898 #ifdef GST_API_VERSION_1
1900 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
1902 mm_player_t* player = (mm_player_t*)hplayer;
1903 GstBuffer *buffer = NULL;
1905 GstFlowReturn gst_ret = GST_FLOW_OK;
1906 int ret = MM_ERROR_NONE;
1910 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1912 /* check current state */
1913 // MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
1916 /* NOTE : we should check and create pipeline again if not created as we destroy
1917 * whole pipeline when stopping in streamming playback
1919 if ( ! player->pipeline )
1921 if ( MM_ERROR_NONE != __gst_realize( player ) )
1923 debug_error("failed to realize before starting. only in streamming\n");
1924 return MM_ERROR_PLAYER_INTERNAL;
1928 debug_msg("app-src: pushing data\n");
1932 debug_error("buf is null\n");
1933 return MM_ERROR_NONE;
1936 buffer = gst_buffer_new ();
1940 debug_log("call eos appsrc\n");
1941 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
1942 return MM_ERROR_NONE;
1945 info.data = (guint8*)(buf);
1946 gst_buffer_set_size(buffer, size);
1947 gst_buffer_map (buffer, &info, GST_MAP_WRITE);
1949 debug_log("feed buffer %p, length %u\n", buf, size);
1950 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
1958 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
1960 mm_player_t* player = (mm_player_t*)hplayer;
1961 GstBuffer *buffer = NULL;
1962 GstFlowReturn gst_ret = GST_FLOW_OK;
1963 int ret = MM_ERROR_NONE;
1967 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1969 /* check current state */
1970 // MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
1973 /* NOTE : we should check and create pipeline again if not created as we destroy
1974 * whole pipeline when stopping in streamming playback
1976 if ( ! player->pipeline )
1978 if ( MM_ERROR_NONE != __gst_realize( player ) )
1980 debug_error("failed to realize before starting. only in streamming\n");
1981 return MM_ERROR_PLAYER_INTERNAL;
1985 debug_msg("app-src: pushing data\n");
1989 debug_error("buf is null\n");
1990 return MM_ERROR_NONE;
1993 buffer = gst_buffer_new ();
1997 debug_log("call eos appsrc\n");
1998 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
1999 return MM_ERROR_NONE;
2002 GST_BUFFER_DATA(buffer) = (guint8*)(buf);
2003 GST_BUFFER_SIZE(buffer) = size;
2005 debug_log("feed buffer %p, length %u\n", buf, size);
2006 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
2015 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
2017 mm_player_t *player = (mm_player_t *)data;
2019 switch (GST_MESSAGE_TYPE (message))
2021 case GST_MESSAGE_TAG:
2022 __mmplayer_gst_extract_tag_from_msg(player, message);
2024 case GST_MESSAGE_DURATION:
2025 __mmplayer_gst_handle_duration(player, message);
2029 return GST_BUS_PASS;
2031 gst_message_unref (message);
2033 return GST_BUS_DROP;
2036 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
2040 return_if_fail(player
2042 && player->pipeline->audiobin
2043 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
2045 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
2052 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
2056 return_if_fail(player
2058 && player->pipeline->audiobin
2059 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
2061 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
2066 static gboolean __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
2068 gboolean ret = FALSE;
2073 return_val_if_fail ( uri , FALSE);
2074 return_val_if_fail ( data , FALSE);
2075 return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
2077 memset(data, 0, sizeof(MMPlayerParseProfile));
2079 if ((path = strstr(uri, "file://")))
2081 if (util_exist_file_path(path + 7)) {
2082 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
2084 if ( util_is_sdp_file ( path ) )
2086 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
2087 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2091 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
2097 debug_warning("could access %s.\n", path);
2100 else if ((path = strstr(uri, "buff://")))
2102 data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
2105 else if ((path = strstr(uri, "rtsp://")))
2108 strcpy(data->uri, uri);
2109 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2113 else if ((path = strstr(uri, "http://")))
2116 strcpy(data->uri, uri);
2117 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
2122 else if ((path = strstr(uri, "https://")))
2125 strcpy(data->uri, uri);
2126 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
2131 else if ((path = strstr(uri, "rtspu://")))
2134 strcpy(data->uri, uri);
2135 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2139 else if ((path = strstr(uri, "rtspr://")))
2141 strcpy(data->uri, path);
2142 char *separater =strstr(path, "*");
2146 char *urgent = separater + strlen("*");
2148 if ((urgent_len = strlen(urgent))) {
2149 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
2150 strcpy(data->urgent, urgent);
2151 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2156 else if ((path = strstr(uri, "mms://")))
2159 strcpy(data->uri, uri);
2160 data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
2164 else if ((path = strstr(uri, "mem://")))
2168 char *buffer = NULL;
2169 char *seperator = strchr(path, ',');
2170 char ext[100] = {0,}, size[100] = {0,};
2173 if ((buffer = strstr(path, "ext="))) {
2174 buffer += strlen("ext=");
2176 if (strlen(buffer)) {
2177 strcpy(ext, buffer);
2179 if ((seperator = strchr(ext, ','))
2180 || (seperator = strchr(ext, ' '))
2181 || (seperator = strchr(ext, '\0'))) {
2182 seperator[0] = '\0';
2187 if ((buffer = strstr(path, "size="))) {
2188 buffer += strlen("size=");
2190 if (strlen(buffer) > 0) {
2191 strcpy(size, buffer);
2193 if ((seperator = strchr(size, ','))
2194 || (seperator = strchr(size, ' '))
2195 || (seperator = strchr(size, '\0'))) {
2196 seperator[0] = '\0';
2199 mem_size = atoi(size);
2204 debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
2205 if ( mem_size && param) {
2207 data->mem_size = mem_size;
2208 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
2215 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
2216 if (util_exist_file_path(uri))
2218 debug_warning("uri has no protocol-prefix. giving 'file://' by default.\n");
2219 g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", uri);
2221 if ( util_is_sdp_file( (char*)uri ) )
2223 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
2224 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
2228 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
2234 debug_error ("invalid uri, could not play..\n");
2235 data->uri_type = MM_PLAYER_URI_TYPE_NONE;
2239 if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
2243 /* dump parse result */
2244 debug_log("profile parsing result ---\n");
2245 debug_warning("incomming uri : %s\n", uri);
2246 debug_log("uri : %s\n", data->uri);
2247 debug_log("uri_type : %d\n", data->uri_type);
2248 debug_log("play_mode : %d\n", data->play_mode);
2249 debug_log("mem : 0x%x\n", (guint)data->mem);
2250 debug_log("mem_size : %d\n", data->mem_size);
2251 debug_log("urgent : %s\n", data->urgent);
2252 debug_log("--------------------------\n");
2259 gboolean _asm_postmsg(gpointer *data)
2261 mm_player_t* player = (mm_player_t*)data;
2262 MMMessageParamType msg = {0, };
2266 return_val_if_fail ( player, FALSE );
2268 msg.union_type = MM_MSG_UNION_CODE;
2269 msg.code = player->sm.event_src;
2271 MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
2276 gboolean _asm_lazy_pause(gpointer *data)
2278 mm_player_t* player = (mm_player_t*)data;
2279 int ret = MM_ERROR_NONE;
2283 return_val_if_fail ( player, FALSE );
2285 if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
2287 debug_log ("Ready to proceed lazy pause\n");
2288 ret = _mmplayer_pause((MMHandleType)player);
2289 if(MM_ERROR_NONE != ret)
2291 debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
2296 debug_log ("Invalid state to proceed lazy pause\n");
2300 if (player->pipeline && player->pipeline->audiobin)
2301 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
2303 player->sm.by_asm_cb = 0; //should be reset here
2311 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
2313 mm_player_t* player = (mm_player_t*) cb_data;
2314 ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
2315 int result = MM_ERROR_NONE;
2316 gboolean lazy_pause = FALSE;
2320 return_val_if_fail ( player && player->pipeline, ASM_CB_RES_IGNORE );
2321 return_val_if_fail ( player->attrs, MM_ERROR_PLAYER_INTERNAL );
2323 if (player->is_sound_extraction)
2325 debug_log("sound extraction is working...so, asm command is ignored.\n");
2329 player->sm.by_asm_cb = 1; // it should be enabled for player state transition with called application command
2330 player->sm.event_src = event_src;
2332 if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG )
2334 int stop_by_asm = 0;
2336 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
2340 else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
2342 /* can use video overlay simultaneously */
2343 /* video resource conflict */
2344 if(player->pipeline->videobin)
2346 if (PLAYER_INI()->multiple_codec_supported)
2348 debug_log("video conflict but, can support to use video overlay simultaneously");
2349 result = _mmplayer_pause((MMHandleType)player);
2350 cb_res = ASM_CB_RES_PAUSE;
2354 debug_log("video conflict, can't support for multiple codec instance");
2355 result = _mmplayer_unrealize((MMHandleType)player);
2356 cb_res = ASM_CB_RES_STOP;
2364 case ASM_COMMAND_PLAY:
2365 debug_warning ("Got unexpected asm command (%d)", command);
2368 case ASM_COMMAND_STOP: // notification case
2370 debug_warning("Got msg from asm to stop");
2372 result = _mmplayer_stop((MMHandleType)player);
2373 if (result != MM_ERROR_NONE)
2375 debug_warning("fail to set stop state by asm");
2376 cb_res = ASM_CB_RES_IGNORE;
2380 cb_res = ASM_CB_RES_STOP;
2382 player->sm.by_asm_cb = 0; // reset because no message any more from asm
2386 case ASM_COMMAND_PAUSE:
2388 debug_warning("Got msg from asm to Pause");
2390 if(event_src == ASM_EVENT_SOURCE_CALL_START
2391 || event_src == ASM_EVENT_SOURCE_ALARM_START
2392 || event_src == ASM_EVENT_SOURCE_MEDIA)
2394 //hold 0.7 second to excute "fadedown mute" effect
2395 debug_warning ("do fade down->pause->undo fade down");
2397 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
2399 result = _mmplayer_pause((MMHandleType)player);
2400 if (result != MM_ERROR_NONE)
2402 debug_warning("fail to set Pause state by asm");
2403 cb_res = ASM_CB_RES_IGNORE;
2406 __mmplayer_undo_sound_fadedown(player);
2408 else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
2410 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
2412 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
2413 g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
2415 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
2416 debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
2421 debug_log ("immediate pause");
2422 result = _mmplayer_pause((MMHandleType)player);
2424 cb_res = ASM_CB_RES_PAUSE;
2428 case ASM_COMMAND_RESUME:
2430 debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
2431 player->sm.by_asm_cb = 0;
2432 //ASM server is single thread daemon. So use g_idle_add() to post resume msg
2433 g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
2434 cb_res = ASM_CB_RES_IGNORE;
2443 player->sm.by_asm_cb = 0;
2451 _mmplayer_create_player(MMHandleType handle) // @
2453 mm_player_t* player = MM_PLAYER_CAST(handle);
2457 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2459 MMTA_ACUM_ITEM_BEGIN("[KPI] media player service create->playing", FALSE);
2461 /* initialize player state */
2462 MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
2463 MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
2464 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
2465 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
2467 /* check current state */
2468 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
2470 /* construct attributes */
2471 player->attrs = _mmplayer_construct_attribute(handle);
2473 if ( !player->attrs )
2475 debug_critical("Failed to construct attributes\n");
2479 /* initialize gstreamer with configured parameter */
2480 if ( ! __mmplayer_gstreamer_init() )
2482 debug_critical("Initializing gstreamer failed\n");
2486 /* initialize factories if not using decodebin */
2487 if ( FALSE == PLAYER_INI()->use_decodebin )
2489 if( player->factories == NULL )
2490 __mmplayer_init_factories(player);
2493 /* create lock. note that g_tread_init() has already called in gst_init() */
2494 player->fsink_lock = g_mutex_new();
2495 if ( ! player->fsink_lock )
2497 debug_critical("Cannot create mutex for command lock\n");
2501 /* create repeat mutex */
2502 player->repeat_thread_mutex = g_mutex_new();
2503 if ( ! player->repeat_thread_mutex )
2505 debug_critical("Cannot create repeat mutex\n");
2509 /* create repeat cond */
2510 player->repeat_thread_cond = g_cond_new();
2511 if ( ! player->repeat_thread_cond )
2513 debug_critical("Cannot create repeat cond\n");
2517 /* create repeat thread */
2518 player->repeat_thread =
2519 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
2520 if ( ! player->repeat_thread )
2525 if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
2527 debug_error("failed to initialize video capture\n");
2531 /* register to asm */
2532 if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
2534 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
2535 debug_error("failed to register asm server\n");
2536 return MM_ERROR_POLICY_INTERNAL;
2539 if (MMPLAYER_IS_HTTP_PD(player))
2541 player->pd_downloader = NULL;
2542 player->pd_file_save_path = NULL;
2545 /* give default value of audio effect setting */
2546 player->bypass_audio_effect = TRUE;
2547 player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
2548 player->playback_rate = DEFAULT_PLAYBACK_RATE;
2550 player->play_subtitle = FALSE;
2551 player->use_textoverlay = FALSE;
2553 /* set player state to null */
2554 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
2555 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
2559 return MM_ERROR_NONE;
2563 if ( player->fsink_lock )
2564 g_mutex_free( player->fsink_lock );
2565 player->fsink_lock = NULL;
2568 if ( player->repeat_thread_cond &&
2569 player->repeat_thread_mutex &&
2570 player->repeat_thread )
2572 player->repeat_thread_exit = TRUE;
2573 g_cond_signal( player->repeat_thread_cond );
2575 g_thread_join( player->repeat_thread );
2576 player->repeat_thread = NULL;
2578 g_mutex_free ( player->repeat_thread_mutex );
2579 player->repeat_thread_mutex = NULL;
2581 g_cond_free ( player->repeat_thread_cond );
2582 player->repeat_thread_cond = NULL;
2584 /* clear repeat thread mutex/cond if still alive
2585 * this can happen if only thread creating has failed
2587 if ( player->repeat_thread_mutex )
2588 g_mutex_free ( player->repeat_thread_mutex );
2590 if ( player->repeat_thread_cond )
2591 g_cond_free ( player->repeat_thread_cond );
2593 /* release attributes */
2594 _mmplayer_deconstruct_attribute(handle);
2596 return MM_ERROR_PLAYER_INTERNAL;
2600 __mmplayer_gstreamer_init(void) // @
2602 static gboolean initialized = FALSE;
2603 static const int max_argc = 50;
2605 gchar** argv = NULL;
2613 debug_log("gstreamer already initialized.\n");
2618 argc = malloc( sizeof(int) );
2619 argv = malloc( sizeof(gchar*) * max_argc );
2621 if ( !argc || !argv )
2624 memset( argv, 0, sizeof(gchar*) * max_argc );
2628 argv[0] = g_strdup( "mmplayer" );
2631 for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
2633 if ( strlen( PLAYER_INI()->gst_param[i] ) > 0 )
2635 argv[*argc] = g_strdup( PLAYER_INI()->gst_param[i] );
2640 /* we would not do fork for scanning plugins */
2641 argv[*argc] = g_strdup("--gst-disable-registry-fork");
2644 /* check disable registry scan */
2645 if ( PLAYER_INI()->skip_rescan )
2647 argv[*argc] = g_strdup("--gst-disable-registry-update");
2651 /* check disable segtrap */
2652 if ( PLAYER_INI()->disable_segtrap )
2654 argv[*argc] = g_strdup("--gst-disable-segtrap");
2658 debug_log("initializing gstreamer with following parameter\n");
2659 debug_log("argc : %d\n", *argc);
2661 for ( i = 0; i < *argc; i++ )
2663 debug_log("argv[%d] : %s\n", i, argv[i]);
2667 /* initializing gstreamer */
2668 __ta__("gst_init time",
2670 if ( ! gst_init_check (argc, &argv, &err))
2672 debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
2683 for ( i = 0; i < *argc; i++ )
2685 MMPLAYER_FREEIF( argv[i] );
2688 MMPLAYER_FREEIF( argv );
2689 MMPLAYER_FREEIF( argc );
2700 MMPLAYER_FREEIF( argv );
2701 MMPLAYER_FREEIF( argc );
2707 __mmplayer_destroy_streaming_ext(mm_player_t* player)
2709 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2711 if (player->pd_downloader)
2712 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
2714 if (MMPLAYER_IS_HTTP_PD(player))
2715 _mmplayer_destroy_pd_downloader((MMHandleType)player);
2717 if (MMPLAYER_IS_STREAMING(player))
2719 if (player->streamer)
2721 __mm_player_streaming_deinitialize (player->streamer);
2722 __mm_player_streaming_destroy(player->streamer);
2723 player->streamer = NULL;
2726 return MM_ERROR_NONE;
2730 _mmplayer_destroy(MMHandleType handle) // @
2732 mm_player_t* player = MM_PLAYER_CAST(handle);
2736 /* check player handle */
2737 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2739 /* destroy can called at anytime */
2740 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
2742 __mmplayer_destroy_streaming_ext(player);
2744 /* release repeat thread */
2745 if ( player->repeat_thread_cond &&
2746 player->repeat_thread_mutex &&
2747 player->repeat_thread )
2749 player->repeat_thread_exit = TRUE;
2750 g_cond_signal( player->repeat_thread_cond );
2752 debug_log("waitting for repeat thread exit\n");
2753 g_thread_join ( player->repeat_thread );
2754 g_mutex_free ( player->repeat_thread_mutex );
2755 g_cond_free ( player->repeat_thread_cond );
2756 debug_log("repeat thread released\n");
2759 if (MM_ERROR_NONE != _mmplayer_release_video_capture(player))
2761 debug_error("failed to release video capture\n");
2762 return MM_ERROR_PLAYER_INTERNAL;
2766 if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
2768 debug_error("failed to deregister asm server\n");
2769 return MM_ERROR_PLAYER_INTERNAL;
2772 /* release pipeline */
2773 if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
2775 debug_error("failed to destory pipeline\n");
2776 return MM_ERROR_PLAYER_INTERNAL;
2779 /* release attributes */
2780 _mmplayer_deconstruct_attribute( handle );
2782 /* release factories */
2783 __mmplayer_release_factories( player );
2786 if ( player->fsink_lock )
2787 g_mutex_free( player->fsink_lock );
2789 if ( player->msg_cb_lock )
2790 g_mutex_free( player->msg_cb_lock );
2792 if (player->lazy_pause_event_id)
2794 g_source_remove (player->lazy_pause_event_id);
2795 player->lazy_pause_event_id = 0;
2800 return MM_ERROR_NONE;
2804 __mmplayer_realize_streaming_ext(mm_player_t* player)
2806 int ret = MM_ERROR_NONE;
2809 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2811 if (MMPLAYER_IS_HTTP_PD(player))
2813 gboolean bret = FALSE;
2815 player->pd_downloader = _mmplayer_create_pd_downloader();
2816 if ( !player->pd_downloader )
2818 debug_error ("Unable to create PD Downloader...");
2819 ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
2822 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
2826 debug_error ("Unable to create PD Downloader...");
2827 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
2836 _mmplayer_realize(MMHandleType hplayer) // @
2838 mm_player_t* player = (mm_player_t*)hplayer;
2841 int application_pid = -1;
2842 gboolean update_registry = FALSE;
2843 MMHandleType attrs = 0;
2844 int ret = MM_ERROR_NONE;
2848 /* check player handle */
2849 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
2851 /* check current state */
2852 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
2854 attrs = MMPLAYER_GET_ATTRS(player);
2857 debug_error("fail to get attributes.\n");
2858 return MM_ERROR_PLAYER_INTERNAL;
2861 mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
2862 player->sm.pid = application_pid;
2864 mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
2865 mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m);
2867 if (! __mmfplayer_parse_profile((const char*)uri, param, &player->profile) )
2869 debug_error("failed to parse profile\n");
2870 return MM_ERROR_PLAYER_INVALID_URI;
2873 /* FIXIT : we can use thouse in player->profile directly */
2874 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
2876 player->mem_buf.buf = (char *)player->profile.mem;
2877 player->mem_buf.len = player->profile.mem_size;
2878 player->mem_buf.offset = 0;
2881 if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
2883 debug_warning("mms protocol is not supported format.\n");
2884 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
2887 if (MMPLAYER_IS_STREAMING(player))
2888 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->live_state_change_timeout;
2890 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
2892 player->videodec_linked = 0;
2893 player->videosink_linked = 0;
2894 player->audiodec_linked = 0;
2895 player->audiosink_linked = 0;
2896 player->textsink_linked = 0;
2898 /* set the subtitle ON default */
2899 player->is_subtitle_off = FALSE;
2901 /* registry should be updated for downloadable codec */
2902 mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
2904 if ( update_registry )
2906 debug_log("updating registry...\n");
2907 gst_update_registry();
2909 /* then we have to rebuild factories */
2910 __mmplayer_release_factories( player );
2911 __mmplayer_init_factories(player);
2914 /* realize pipeline */
2915 ret = __gst_realize( player );
2916 if ( ret != MM_ERROR_NONE )
2918 debug_error("fail to realize the player.\n");
2922 ret = __mmplayer_realize_streaming_ext(player);
2931 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
2934 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
2936 /* destroy can called at anytime */
2937 if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
2939 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
2940 player->pd_downloader = NULL;
2944 return MM_ERROR_NONE;
2948 _mmplayer_unrealize(MMHandleType hplayer) // @
2950 mm_player_t* player = (mm_player_t*)hplayer;
2951 int ret = MM_ERROR_NONE;
2955 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
2957 /* check current state */
2958 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
2960 __mmplayer_unrealize_streaming_ext(player);
2962 /* unrealize pipeline */
2963 ret = __gst_unrealize( player );
2965 /* set player state if success */
2966 if ( MM_ERROR_NONE == ret )
2968 if (player->sm.state != ASM_STATE_STOP) {
2969 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP);
2972 debug_error("failed to set asm state to STOP\n");
2984 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
2986 mm_player_t* player = (mm_player_t*)hplayer;
2988 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
2990 return __gst_set_message_callback(player, callback, user_param);
2994 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
2996 mm_player_t *player = (mm_player_t*)hplayer;
2998 return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
3000 *state = MMPLAYER_CURRENT_STATE(player);
3002 return MM_ERROR_NONE;
3007 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
3009 mm_player_t* player = (mm_player_t*) hplayer;
3010 GstElement* vol_element = NULL;
3015 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3017 debug_log("volume [L]=%f:[R]=%f\n",
3018 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
3020 /* invalid factor range or not */
3021 for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
3023 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
3024 debug_error("Invalid factor! (valid factor:0~1.0)\n");
3025 return MM_ERROR_INVALID_ARGUMENT;
3029 /* Save volume to handle. Currently the first array element will be saved. */
3030 player->sound.volume = volume.level[0];
3032 /* check pipeline handle */
3033 if ( ! player->pipeline || ! player->pipeline->audiobin )
3035 debug_log("audiobin is not created yet\n");
3036 debug_log("but, current stored volume will be set when it's created.\n");
3038 /* NOTE : stored volume will be used in create_audiobin
3039 * returning MM_ERROR_NONE here makes application to able to
3040 * set volume at anytime.
3042 return MM_ERROR_NONE;
3045 /* setting volume to volume element */
3046 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3050 debug_log("volume is set [%f]\n", player->sound.volume);
3051 g_object_set(vol_element, "volume", player->sound.volume, NULL);
3056 return MM_ERROR_NONE;
3061 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
3063 mm_player_t* player = (mm_player_t*) hplayer;
3068 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3069 return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
3071 /* returning stored volume */
3072 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
3073 volume->level[i] = player->sound.volume;
3077 return MM_ERROR_NONE;
3083 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
3085 mm_player_t* player = (mm_player_t*) hplayer;
3086 GstElement* vol_element = NULL;
3090 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3092 debug_log("mute : %d\n", mute);
3094 /* mute value shoud 0 or 1 */
3095 if ( mute != 0 && mute != 1 )
3097 debug_error("bad mute value\n");
3099 /* FIXIT : definitly, we need _BAD_PARAM error code */
3100 return MM_ERROR_INVALID_ARGUMENT;
3104 /* just hold mute value if pipeline is not ready */
3105 if ( !player->pipeline || !player->pipeline->audiobin )
3107 debug_log("pipeline is not ready. holding mute value\n");
3108 player->sound.mute = mute;
3109 return MM_ERROR_NONE;
3113 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3115 /* NOTE : volume will only created when the bt is enabled */
3118 g_object_set(vol_element, "mute", mute, NULL);
3122 debug_log("volume elemnet is not created. using volume in audiosink\n");
3125 player->sound.mute = mute;
3129 return MM_ERROR_NONE;
3133 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
3135 mm_player_t* player = (mm_player_t*) hplayer;
3136 GstElement* vol_element = NULL;
3140 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3141 return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
3143 /* just hold mute value if pipeline is not ready */
3144 if ( !player->pipeline || !player->pipeline->audiobin )
3146 debug_log("pipeline is not ready. returning stored value\n");
3147 *pmute = player->sound.mute;
3148 return MM_ERROR_NONE;
3152 vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
3156 g_object_get(vol_element, "mute", pmute, NULL);
3157 debug_log("mute=%d\n\n", *pmute);
3161 *pmute = player->sound.mute;
3166 return MM_ERROR_NONE;
3170 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
3172 mm_player_t* player = (mm_player_t*) hplayer;
3176 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3177 return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
3179 player->video_stream_cb = callback;
3180 player->video_stream_cb_user_param = user_param;
3181 player->use_video_stream = TRUE;
3182 debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
3186 return MM_ERROR_NONE;
3190 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
3192 mm_player_t* player = (mm_player_t*) hplayer;
3196 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3197 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3199 player->audio_stream_cb = callback;
3200 player->audio_stream_cb_user_param = user_param;
3201 debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
3205 return MM_ERROR_NONE;
3209 _mmplayer_set_audiobuffer_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
3211 mm_player_t* player = (mm_player_t*) hplayer;
3215 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3216 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3218 player->audio_buffer_cb = callback;
3219 player->audio_buffer_cb_user_param = user_param;
3220 debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_buffer_cb);
3224 return MM_ERROR_NONE;
3228 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
3230 mm_player_t* player = (mm_player_t*) hplayer;
3234 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3235 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3237 player->need_data_cb = callback;
3238 player->buffer_cb_user_param = user_param;
3240 debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
3244 return MM_ERROR_NONE;
3248 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
3250 mm_player_t* player = (mm_player_t*) hplayer;
3254 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3255 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3257 player->enough_data_cb = callback;
3258 player->buffer_cb_user_param = user_param;
3260 debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
3264 return MM_ERROR_NONE;
3268 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
3270 mm_player_t* player = (mm_player_t*) hplayer;
3274 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3275 return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
3277 player->seek_data_cb = callback;
3278 player->buffer_cb_user_param = user_param;
3280 debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
3284 return MM_ERROR_NONE;
3288 _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @
3290 mm_player_t* player = (mm_player_t*) hplayer;
3294 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3295 return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
3297 player->video_frame_render_error_cb = callback;
3298 player->video_frame_render_error_cb_user_param = user_param;
3300 debug_log("Video frame render error cb Handle value is %p : %p\n", player, player->video_frame_render_error_cb);
3304 return MM_ERROR_NONE;
3308 __mmplayer_start_streaming_ext(mm_player_t *player)
3310 gint ret = MM_ERROR_NONE;
3313 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3315 if (MMPLAYER_IS_HTTP_PD(player))
3317 if ( !player->pd_downloader )
3319 ret = __mmplayer_realize_streaming_ext(player);
3321 if ( ret != MM_ERROR_NONE)
3323 debug_error ("failed to realize streaming ext\n");
3328 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
3330 ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
3333 debug_error ("ERROR while starting PD...\n");
3334 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3336 ret = MM_ERROR_NONE;
3345 _mmplayer_start(MMHandleType hplayer) // @
3347 mm_player_t* player = (mm_player_t*) hplayer;
3348 gint ret = MM_ERROR_NONE;
3352 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3354 /* check current state */
3355 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
3357 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
3358 if ( ret != MM_ERROR_NONE )
3360 debug_error("failed to set asm state to PLAYING\n");
3364 /* NOTE : we should check and create pipeline again if not created as we destroy
3365 * whole pipeline when stopping in streamming playback
3367 if ( ! player->pipeline )
3369 ret = __gst_realize( player );
3370 if ( MM_ERROR_NONE != ret )
3372 debug_error("failed to realize before starting. only in streamming\n");
3377 ret = __mmplayer_start_streaming_ext(player);
3378 if ( ret != MM_ERROR_NONE )
3380 debug_error("failed to start streaming ext \n");
3383 /* start pipeline */
3384 ret = __gst_start( player );
3385 if ( ret != MM_ERROR_NONE )
3387 debug_error("failed to start player.\n");
3395 /* NOTE : it should be able to call 'stop' anytime*/
3397 _mmplayer_stop(MMHandleType hplayer) // @
3399 mm_player_t* player = (mm_player_t*)hplayer;
3400 int ret = MM_ERROR_NONE;
3404 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3406 /* check current state */
3407 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
3409 /* NOTE : application should not wait for EOS after calling STOP */
3410 __mmplayer_cancel_delayed_eos( player );
3412 __mmplayer_unrealize_streaming_ext(player);
3415 ret = __gst_stop( player );
3417 if ( ret != MM_ERROR_NONE )
3419 debug_error("failed to stop player.\n");
3428 _mmplayer_pause(MMHandleType hplayer) // @
3430 mm_player_t* player = (mm_player_t*)hplayer;
3431 #ifndef GST_API_VERSION_1
3432 GstFormat fmt = GST_FORMAT_TIME;
3434 gint64 pos_msec = 0;
3435 gboolean async = FALSE;
3436 gint ret = MM_ERROR_NONE;
3440 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3442 /* check current state */
3443 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
3445 switch (MMPLAYER_CURRENT_STATE(player))
3447 case MM_PLAYER_STATE_READY:
3449 /* check prepare async or not.
3450 * In the case of streaming playback, it's recommned to avoid blocking wait.
3452 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
3453 debug_log("prepare mode : %s", (async ? "async" : "sync"));
3457 case MM_PLAYER_STATE_PLAYING:
3459 /* NOTE : store current point to overcome some bad operation
3460 * ( returning zero when getting current position in paused state) of some
3463 #ifdef GST_API_VERSION_1
3464 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
3466 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
3469 debug_warning("getting current position failed in paused\n");
3471 player->last_position = pos_msec;
3476 /* pause pipeline */
3477 ret = __gst_pause( player, async );
3479 if ( ret != MM_ERROR_NONE )
3481 debug_error("failed to pause player. ret : 0x%x\n", ret);
3490 _mmplayer_resume(MMHandleType hplayer)
3492 mm_player_t* player = (mm_player_t*)hplayer;
3493 int ret = MM_ERROR_NONE;
3494 gboolean async = FALSE;
3498 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3500 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
3503 debug_error("failed to set asm state to PLAYING\n");
3507 /* check current state */
3508 MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
3510 /* resume pipeline */
3511 ret = __gst_resume( player, FALSE );
3513 if ( ret != MM_ERROR_NONE )
3515 debug_error("failed to resume player.\n");
3525 __mmplayer_set_play_count(mm_player_t* player, gint count)
3527 MMHandleType attrs = 0;
3531 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3533 attrs = MMPLAYER_GET_ATTRS(player);
3536 debug_error("fail to get attributes.\n");
3537 return MM_ERROR_PLAYER_INTERNAL;
3540 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
3541 if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
3542 debug_error("failed to commit\n");
3546 return MM_ERROR_NONE;
3550 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
3552 mm_player_t* player = (mm_player_t*)hplayer;
3553 gint64 start_pos = 0;
3559 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3560 return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
3562 player->section_repeat = TRUE;
3563 player->section_repeat_start = start;
3564 player->section_repeat_end = end;
3566 start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
3567 end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
3569 __mmplayer_set_play_count( player, infinity );
3571 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3572 player->playback_rate,
3574 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3575 GST_SEEK_TYPE_SET, start_pos,
3576 GST_SEEK_TYPE_SET, end_pos)))
3578 debug_error("failed to activate section repeat\n");
3580 return MM_ERROR_PLAYER_SEEK;
3583 debug_log("succeeded to set section repeat from %d to %d\n",
3584 player->section_repeat_start, player->section_repeat_end);
3588 return MM_ERROR_NONE;
3592 __mmplayer_set_pcm_extraction(mm_player_t* player)
3594 guint64 start_nsec = 0;
3595 guint64 end_nsec = 0;
3596 guint64 dur_nsec = 0;
3597 guint64 dur_msec = 0;
3598 #ifndef GST_API_VERSION_1
3599 GstFormat fmt = GST_FORMAT_TIME;
3601 int required_start = 0;
3602 int required_end = 0;
3607 return_val_if_fail( player, FALSE );
3609 mm_attrs_multiple_get(player->attrs,
3611 "pcm_extraction_start_msec", &required_start,
3612 "pcm_extraction_end_msec", &required_end,
3615 debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
3617 if (required_start == 0 && required_end == 0)
3619 debug_log("extracting entire stream");
3620 return MM_ERROR_NONE;
3622 else if (required_start < 0 || required_start > required_end || required_end < 0 )
3624 debug_log("invalid range for pcm extraction");
3625 return MM_ERROR_INVALID_ARGUMENT;
3629 #ifdef GST_API_VERSION_1
3630 ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
3632 ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
3636 debug_error("failed to get duration");
3637 return MM_ERROR_PLAYER_INTERNAL;
3639 dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
3641 if (dur_msec < required_end) // FIXME
3643 debug_log("invalid end pos for pcm extraction");
3644 return MM_ERROR_INVALID_ARGUMENT;
3647 start_nsec = required_start * G_GINT64_CONSTANT(1000000);
3648 end_nsec = required_end * G_GINT64_CONSTANT(1000000);
3650 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3653 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3654 GST_SEEK_TYPE_SET, start_nsec,
3655 GST_SEEK_TYPE_SET, end_nsec)))
3657 debug_error("failed to seek for pcm extraction\n");
3659 return MM_ERROR_PLAYER_SEEK;
3662 debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
3666 return MM_ERROR_NONE;
3670 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
3672 mm_player_t* player = (mm_player_t*)hplayer;
3674 #ifndef GST_API_VERSION_1
3675 GstFormat fmt = GST_FORMAT_TIME;
3681 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3683 player->section_repeat = FALSE;
3685 __mmplayer_set_play_count( player, onetime );
3686 #ifdef GST_API_VERSION_1
3687 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_pos);
3689 gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
3692 if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3695 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3696 GST_SEEK_TYPE_SET, cur_pos,
3697 GST_SEEK_TYPE_SET, player->duration )))
3699 debug_error("failed to deactivate section repeat\n");
3701 return MM_ERROR_PLAYER_SEEK;
3706 return MM_ERROR_NONE;
3710 _mmplayer_set_playspeed(MMHandleType hplayer, gdouble rate)
3712 mm_player_t* player = (mm_player_t*)hplayer;
3713 signed long long pos_msec = 0;
3714 int ret = MM_ERROR_NONE;
3716 #ifndef GST_API_VERSION_1
3717 GstFormat format =GST_FORMAT_TIME;
3719 MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
3722 return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3723 return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
3725 /* The sound of video is not supported under 0.0 and over 2.0. */
3726 if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
3728 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
3731 _mmplayer_set_mute(hplayer, mute);
3733 if (player->playback_rate == rate)
3734 return MM_ERROR_NONE;
3736 /* If the position is reached at start potion during fast backward, EOS is posted.
3737 * So, This EOS have to be classified with it which is posted at reaching the end of stream.
3739 player->playback_rate = rate;
3741 current_state = MMPLAYER_CURRENT_STATE(player);
3742 #ifdef GST_API_VERSION_1
3743 if ( current_state != MM_PLAYER_STATE_PAUSED )
3744 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
3746 if ( current_state != MM_PLAYER_STATE_PAUSED )
3747 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
3750 debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
3752 if ( ( current_state == MM_PLAYER_STATE_PAUSED )
3754 //|| ( player->last_position != 0 && pos_msec == 0 ) )
3756 debug_warning("returning last point : %lld\n", player->last_position );
3757 pos_msec = player->last_position;
3760 if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3763 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3764 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
3765 GST_SEEK_TYPE_SET, pos_msec,
3766 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
3767 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
3769 debug_error("failed to set speed playback\n");
3770 return MM_ERROR_PLAYER_SEEK;
3773 debug_log("succeeded to set speed playback as %fl\n", rate);
3777 return MM_ERROR_NONE;;
3781 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
3783 mm_player_t* player = (mm_player_t*)hplayer;
3784 int ret = MM_ERROR_NONE;
3788 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3790 ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
3798 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
3800 mm_player_t* player = (mm_player_t*)hplayer;
3801 int ret = MM_ERROR_NONE;
3803 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3805 ret = __gst_get_position ( player, format, position );
3811 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
3813 mm_player_t* player = (mm_player_t*)hplayer;
3814 int ret = MM_ERROR_NONE;
3816 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3818 ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
3824 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
3826 mm_player_t* player = (mm_player_t*)hplayer;
3827 int ret = MM_ERROR_NONE;
3831 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3833 ret = __gst_adjust_subtitle_position(player, format, position);
3841 __mmplayer_is_midi_type( gchar* str_caps)
3843 if ( ( g_strrstr(str_caps, "audio/midi") ) ||
3844 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
3845 ( g_strrstr(str_caps, "application/x-smaf") ) ||
3846 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
3847 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
3848 ( g_strrstr(str_caps, "audio/xmf") ) ||
3849 ( g_strrstr(str_caps, "audio/mxmf") ) )
3851 debug_log("midi\n");
3860 __mmplayer_is_amr_type (gchar *str_caps)
3862 if ((g_strrstr(str_caps, "AMR")) ||
3863 (g_strrstr(str_caps, "amr")))
3871 __mmplayer_is_only_mp3_type (gchar *str_caps)
3873 if (g_strrstr(str_caps, "application/x-id3") ||
3874 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
3882 __mmplayer_typefind_have_type( GstElement *tf, guint probability, // @
3883 GstCaps *caps, gpointer data)
3885 mm_player_t* player = (mm_player_t*)data;
3890 return_if_fail( player && tf && caps );
3892 /* store type string */
3893 MMPLAYER_FREEIF(player->type);
3894 player->type = gst_caps_to_string(caps);
3896 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
3898 /* midi type should be stored because it will be used to set audio gain in avsysaudiosink */
3899 if ( __mmplayer_is_midi_type(player->type))
3901 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
3903 else if (__mmplayer_is_amr_type(player->type))
3905 player->bypass_audio_effect = FALSE;
3906 if ( (PLAYER_INI()->use_audio_effect_preset || PLAYER_INI()->use_audio_effect_custom) )
3908 if ( player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_PRESET )
3910 if (!_mmplayer_audio_effect_preset_apply(player, player->audio_effect_info.preset))
3912 debug_msg("apply audio effect(preset:%d) setting success\n",player->audio_effect_info.preset);
3915 else if ( player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM )
3917 if (!_mmplayer_audio_effect_custom_apply(player))
3919 debug_msg("apply audio effect(custom) setting success\n");
3924 else if ( g_strrstr(player->type, "application/x-hls"))
3926 /* If it can't know exact type when it parses uri because of redirection case,
3927 * it will be fixed by typefinder here.
3929 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
3932 pad = gst_element_get_static_pad(tf, "src");
3935 debug_error("fail to get typefind src pad.\n");
3940 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
3942 gboolean async = FALSE;
3944 debug_error("failed to autoplug %s\n", player->type);
3945 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
3947 if ( async && player->msg_posted == FALSE )
3949 __mmplayer_handle_missed_plugin( player );
3955 /* finish autopluging if no dynamic pad waiting */
3956 if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
3958 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
3960 __mmplayer_pipeline_complete( NULL, (gpointer)player );
3965 gst_object_unref( GST_OBJECT(pad) );
3973 __mmplayer_warm_up_video_codec( mm_player_t* player, GstElementFactory *factory)
3975 GstElement *element;
3976 GstStateChangeReturn ret;
3977 gboolean usable = TRUE;
3979 return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3980 return_val_if_fail ( factory, MM_ERROR_COMMON_INVALID_ARGUMENT );
3982 element = gst_element_factory_create (factory, NULL);
3984 ret = gst_element_set_state (element, GST_STATE_READY);
3986 if (ret != GST_STATE_CHANGE_SUCCESS)
3988 #ifdef GST_API_VERSION_1
3989 debug_error ("resource conflict so, %s unusable\n", gst_object_get_name (GST_OBJECT (factory)));
3991 debug_error ("resource conflict so, %s unusable\n", GST_PLUGIN_FEATURE_NAME (factory));
3996 gst_element_set_state (element, GST_STATE_NULL);
3997 gst_object_unref (element);
4002 /* it will return first created element */
4004 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
4006 MMPlayerGstElement* mainbin = NULL;
4007 const char* mime = NULL;
4008 const GList* item = NULL;
4009 const gchar* klass = NULL;
4010 GstCaps* res = NULL;
4011 gboolean skip = FALSE;
4012 GstPad* queue_pad = NULL;
4013 GstElement* queue = NULL;
4014 GstElement *element = NULL;
4018 return_val_if_fail( player && player->pipeline && player->pipeline->mainbin, FALSE );
4020 mainbin = player->pipeline->mainbin;
4022 mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
4024 /* return if we got raw output */
4025 if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw")
4026 || g_str_has_prefix(mime, "video/x-surface")
4027 || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup"))
4030 element = (GstElement*)gst_pad_get_parent(pad);
4031 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
4032 * No queue will be added. I think it can caused breaking sound when playing raw audio
4033 * frames but there's no different. Decodebin also doesn't add with those wav fils.
4034 * Anyway, currentely raw-queue seems not necessary.
4037 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
4038 * has linked. if so, we need to add queue for quality of output. note that
4039 * decodebin also has same problem.
4041 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
4043 /* add queue if needed */
4044 if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader")
4045 || g_strrstr(klass, "Parse")) && !g_str_has_prefix(mime, "text"))
4047 debug_log("adding raw queue\n");
4049 queue = gst_element_factory_make("queue", NULL);
4052 debug_warning("failed to create queue\n");
4057 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
4059 debug_warning("failed to set state READY to queue\n");
4063 /* add to pipeline */
4064 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
4066 debug_warning("failed to add queue\n");
4071 queue_pad = gst_element_get_static_pad(queue, "sink");
4073 if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
4075 debug_warning("failed to link queue\n");
4078 gst_object_unref ( GST_OBJECT(queue_pad) );
4082 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
4084 debug_warning("failed to set state READY to queue\n");
4088 /* replace given pad to queue:src */
4089 pad = gst_element_get_static_pad(queue, "src");
4092 debug_warning("failed to get pad from queue\n");
4097 /* check if player can do start continually */
4098 MMPLAYER_CHECK_CMD_IF_EXIT(player);
4100 if(__mmplayer_link_sink(player,pad))
4101 __mmplayer_gst_decode_callback(element, pad, FALSE, player);
4103 gst_object_unref( GST_OBJECT(element));
4109 item = player->factories;
4110 for(; item != NULL ; item = item->next)
4112 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
4118 /* filtering exclude keyword */
4119 #ifdef GST_API_VERSION_1
4120 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
4122 if ( g_strrstr(gst_object_get_name (GST_OBJECT (factory)),
4123 PLAYER_INI()->exclude_element_keyword[idx]) )
4125 debug_warning("skipping [%s] by exculde keyword [%s]\n",
4126 gst_object_get_name (GST_OBJECT (factory)),
4127 PLAYER_INI()->exclude_element_keyword[idx] );
4134 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
4136 if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
4137 PLAYER_INI()->exclude_element_keyword[idx] ) )
4139 debug_warning("skipping [%s] by exculde keyword [%s]\n",
4140 GST_PLUGIN_FEATURE_NAME (factory),
4141 PLAYER_INI()->exclude_element_keyword[idx] );
4149 if ( skip ) continue;
4151 /* check factory class for filtering */
4152 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
4154 /* NOTE : msl don't need to use image plugins.
4155 * So, those plugins should be skipped for error handling.
4157 if ( g_strrstr(klass, "Codec/Decoder/Image") )
4159 #ifdef GST_API_VERSION_1
4160 debug_log("skipping [%s] by not required\n",
4161 gst_object_get_name (GST_OBJECT (factory)) );
4163 debug_log("skipping [%s] by not required\n",
4164 GST_PLUGIN_FEATURE_NAME (factory) );
4169 /* check pad compatability */
4170 for(pads = gst_element_factory_get_static_pad_templates(factory);
4171 pads != NULL; pads=pads->next)
4173 GstStaticPadTemplate *temp1 = pads->data;
4174 GstCaps* static_caps = NULL;
4176 if( temp1->direction != GST_PAD_SINK ||
4177 temp1->presence != GST_PAD_ALWAYS)
4180 if ( GST_IS_CAPS( &temp1->static_caps.caps) )
4182 /* using existing caps */
4183 static_caps = gst_caps_ref( &temp1->static_caps.caps );
4188 static_caps = gst_caps_from_string ( temp1->static_caps.string );
4191 res = gst_caps_intersect(caps, static_caps);
4193 gst_caps_unref( static_caps );
4196 if( res && !gst_caps_is_empty(res) )
4198 #ifdef GST_API_VERSION_1
4199 GstElement *new_element;
4200 GList *elements = player->parsers;
4201 char *name_template = g_strdup(temp1->name_template);
4202 gchar *name_to_plug = gst_object_get_name (GST_OBJECT (factory));
4204 gst_caps_unref(res);
4206 debug_log("found %s to plug\n", name_to_plug);
4208 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
4209 if ( ! new_element )
4211 debug_error("failed to create element [%s]. continue with next.\n",
4212 gst_object_get_name (GST_OBJECT (factory)));
4214 MMPLAYER_FREEIF(name_template);
4219 GstElement *new_element;
4220 GList *elements = player->parsers;
4221 char *name_template = g_strdup(temp1->name_template);
4222 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
4224 gst_caps_unref(res);
4226 debug_log("found %s to plug\n", name_to_plug);
4228 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
4229 if ( ! new_element )
4231 debug_error("failed to create element [%s]. continue with next.\n",
4232 GST_PLUGIN_FEATURE_NAME (factory));
4234 MMPLAYER_FREEIF(name_template);
4240 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
4241 * because parser can accept its own output as input.
4243 if (g_strrstr(klass, "Parser"))
4245 gchar *selected = NULL;
4247 for ( ; elements; elements = g_list_next(elements))
4249 gchar *element_name = elements->data;
4251 if (g_strrstr(element_name, name_to_plug))
4253 debug_log("but, %s already linked, so skipping it\n", name_to_plug);
4260 selected = g_strdup(name_to_plug);
4262 player->parsers = g_list_append(player->parsers, selected);
4265 /* store specific handles for futher control */
4266 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
4268 /* FIXIT : first value will be overwritten if there's more
4269 * than 1 demuxer/parser
4271 debug_log("plugged element is demuxer. take it\n");
4272 mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
4273 mainbin[MMPLAYER_M_DEMUX].gst = new_element;
4275 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
4277 if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
4279 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
4280 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
4281 mainbin[MMPLAYER_M_DEC1].gst = new_element;
4283 else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
4285 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
4286 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
4287 mainbin[MMPLAYER_M_DEC2].gst = new_element;
4289 /* NOTE : IF one codec is found, add it to supported_codec and remove from
4290 * missing plugin. Both of them are used to check what's supported codec
4291 * before returning result of play start. And, missing plugin should be
4292 * updated here for multi track files.
4294 if(g_str_has_prefix(mime, "video"))
4296 GstPad *src_pad = NULL;
4297 GstPadTemplate *pad_templ = NULL;
4298 GstCaps *caps = NULL;
4299 gchar *caps_type = NULL;
4301 debug_log("found VIDEO decoder\n");
4302 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
4303 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
4305 src_pad = gst_element_get_static_pad (new_element, "src");
4306 pad_templ = gst_pad_get_pad_template (src_pad);
4307 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
4309 caps_type = gst_caps_to_string(caps);
4311 if ( g_strrstr( caps_type, "ST12") )
4312 player->is_nv12_tiled = TRUE;
4315 MMPLAYER_FREEIF( caps_type );
4316 gst_object_unref (src_pad);
4318 else if (g_str_has_prefix(mime, "audio"))
4320 debug_log("found AUDIO decoder\n");
4321 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
4322 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
4325 if ( ! __mmplayer_close_link(player, pad, new_element,
4326 name_template,gst_element_factory_get_static_pad_templates(factory)) )
4328 if (player->keep_detecting_vcodec)
4331 /* Link is failed even though a supportable codec is found. */
4332 __mmplayer_check_not_supported_codec(player, (gchar *)mime);
4334 MMPLAYER_FREEIF(name_template);
4335 debug_error("failed to call _close_link\n");
4339 MMPLAYER_FREEIF(name_template);
4343 gst_caps_unref(res);
4349 /* There is no available codec. */
4350 __mmplayer_check_not_supported_codec(player,(gchar *)mime);
4359 gst_object_unref( queue );
4363 gst_object_unref( queue_pad );
4366 gst_object_unref ( element );
4373 int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime)
4377 return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4378 return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
4380 debug_log("mimetype to check: %s\n", mime );
4382 /* add missing plugin */
4383 /* NOTE : msl should check missing plugin for image mime type.
4384 * Some motion jpeg clips can have playable audio track.
4385 * So, msl have to play audio after displaying popup written video format not supported.
4387 if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
4389 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
4391 debug_log("not found demuxer\n");
4392 player->not_found_demuxer = TRUE;
4393 player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
4399 if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
4401 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
4402 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
4404 /* check that clip have multi tracks or not */
4405 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
4407 debug_log("video plugin is already linked\n");
4411 debug_warning("add VIDEO to missing plugin\n");
4412 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
4415 else if ( g_str_has_prefix(mime, "audio") )
4417 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
4419 debug_log("audio plugin is already linked\n");
4423 debug_warning("add AUDIO to missing plugin\n");
4424 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
4431 return MM_ERROR_NONE;
4435 static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) // @
4437 mm_player_t* player = (mm_player_t*)data;
4441 return_if_fail( player );
4443 /* remove fakesink */
4444 if ( ! __mmplayer_gst_remove_fakesink( player,
4445 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
4447 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
4448 * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
4449 * source element are not same. To overcome this situation, this function will called
4450 * several places and several times. Therefore, this is not an error case.
4454 debug_log("pipeline has completely constructed\n");
4456 player->pipeline_is_constructed = TRUE;
4458 if ( ( PLAYER_INI()->async_start ) &&
4459 ( player->msg_posted == FALSE ) &&
4460 ( player->cmd >= MMPLAYER_COMMAND_START ))
4462 __mmplayer_handle_missed_plugin( player );
4465 MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complete" );
4468 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
4472 return_val_if_fail ( player, FALSE );
4475 if ( MMPLAYER_IS_STREAMING(player) )
4478 /* This callback can be set to music player only. */
4479 if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
4481 debug_warning("audio callback is not supported for video");
4485 if (player->audio_stream_cb)
4490 #ifdef GST_API_VERSION_1
4491 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
4493 pad = gst_element_get_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
4498 debug_error("failed to get sink pad from audiosink to probe data\n");
4502 #ifdef GST_API_VERSION_1
4503 player->audio_cb_probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
4504 __mmplayer_audio_stream_probe, player, NULL);
4506 player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
4507 G_CALLBACK (__mmplayer_audio_stream_probe), player);
4510 gst_object_unref (pad);
4517 debug_error("There is no audio callback to configure.\n");
4527 __mmplayer_init_factories(mm_player_t* player) // @
4531 return_if_fail ( player );
4533 #ifdef GST_API_VERSION_1
4534 player->factories = gst_registry_feature_filter(gst_registry_get(),
4535 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
4537 player->factories = gst_registry_feature_filter(gst_registry_get_default(),
4538 (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
4541 player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
4547 __mmplayer_release_factories(mm_player_t* player) // @
4551 return_if_fail ( player );
4553 if (player->factories)
4555 gst_plugin_feature_list_free (player->factories);
4556 player->factories = NULL;
4563 __mmplayer_release_misc(mm_player_t* player)
4568 return_if_fail ( player );
4570 player->use_video_stream = FALSE;
4571 player->video_stream_cb = NULL;
4572 player->video_stream_cb_user_param = NULL;
4574 player->audio_stream_cb = NULL;
4575 player->audio_stream_cb_user_param = NULL;
4577 player->audio_buffer_cb = NULL;
4578 player->audio_buffer_cb_user_param = NULL;
4580 player->sent_bos = FALSE;
4581 player->playback_rate = DEFAULT_PLAYBACK_RATE;
4583 player->doing_seek = FALSE;
4585 player->streamer = NULL;
4586 player->updated_bitrate_count = 0;
4587 player->total_bitrate = 0;
4588 player->updated_maximum_bitrate_count = 0;
4589 player->total_maximum_bitrate = 0;
4591 player->not_found_demuxer = 0;
4593 player->last_position = 0;
4594 player->duration = 0;
4595 player->http_content_size = 0;
4596 player->not_supported_codec = MISSING_PLUGIN_NONE;
4597 player->can_support_codec = FOUND_PLUGIN_NONE;
4598 player->pending_seek.is_pending = FALSE;
4599 player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
4600 player->pending_seek.pos = 0;
4601 player->msg_posted = FALSE;
4602 player->has_many_types = FALSE;
4604 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
4606 player->bitrate[i] = 0;
4607 player->maximum_bitrate[i] = 0;
4610 /* clean found parsers */
4611 if (player->parsers)
4613 g_list_free(player->parsers);
4614 player->parsers = NULL;
4617 MMPLAYER_FREEIF(player->album_art);
4619 /* free memory related to audio effect */
4620 if(player->audio_effect_info.custom_ext_level_for_plugin)
4622 free(player->audio_effect_info.custom_ext_level_for_plugin);
4628 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
4630 GstElement *element = NULL;
4633 debug_log("creating %s to plug\n", name);
4635 element = gst_element_factory_make(name, NULL);
4638 debug_error("failed to create queue\n");
4642 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
4644 debug_error("failed to set state READY to %s\n", name);
4648 if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
4650 debug_error("failed to add %s\n", name);
4654 sinkpad = gst_element_get_static_pad(element, "sink");
4656 if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
4658 debug_error("failed to link %s\n", name);
4659 gst_object_unref (sinkpad);
4664 debug_log("linked %s to pipeline successfully\n", name);
4666 gst_object_unref (sinkpad);
4672 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
4673 const char *padname, const GList *templlist)
4676 gboolean has_dynamic_pads = FALSE;
4677 gboolean has_many_types = FALSE;
4678 const char *klass = NULL;
4679 GstStaticPadTemplate *padtemplate = NULL;
4680 GstElementFactory *factory = NULL;
4681 GstElement* queue = NULL;
4682 GstElement* parser = NULL;
4683 GstPad *pssrcpad = NULL;
4684 GstPad *qsrcpad = NULL, *qsinkpad = NULL;
4685 MMPlayerGstElement *mainbin = NULL;
4686 GstStructure* str = NULL;
4687 GstCaps* srccaps = NULL;
4688 GstState warmup = GST_STATE_READY;
4689 gboolean isvideo_decoder = FALSE;
4690 guint q_max_size_time = 0;
4694 return_val_if_fail ( player &&
4696 player->pipeline->mainbin,
4699 mainbin = player->pipeline->mainbin;
4701 debug_log("plugging pad %s:%s to newly create %s:%s\n",
4702 GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
4703 GST_PAD_NAME( srcpad ),
4704 GST_ELEMENT_NAME( sinkelement ),
4707 factory = gst_element_get_factory(sinkelement);
4708 klass = gst_element_factory_get_klass(factory);
4710 /* check if player can do start continually */
4711 MMPLAYER_CHECK_CMD_IF_EXIT(player);
4713 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, warmup) )
4715 if (isvideo_decoder)
4716 player->keep_detecting_vcodec = TRUE;
4718 debug_error("failed to set %d state to %s\n", warmup, GST_ELEMENT_NAME( sinkelement ));
4722 /* add to pipeline */
4723 if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
4725 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
4729 debug_log("element klass : %s\n", klass);
4731 /* added to support multi track files */
4732 /* only decoder case and any of the video/audio still need to link*/
4733 if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
4737 name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
4739 if (g_strrstr(name, "mpegtsdemux"))
4741 gchar *demux_caps = NULL;
4742 gchar *parser_name = NULL;
4743 GstCaps *dcaps = NULL;
4745 #ifdef GST_API_VERSION_1
4746 dcaps = gst_pad_get_current_caps(srcpad);
4748 dcaps = gst_pad_get_caps(srcpad);
4750 demux_caps = gst_caps_to_string(dcaps);
4752 if (g_strrstr(demux_caps, "video/x-h264"))
4754 parser_name = g_strdup("h264parse");
4756 else if (g_strrstr(demux_caps, "video/mpeg"))
4758 parser_name = g_strdup("mpeg4videoparse");
4761 gst_caps_unref(dcaps);
4762 MMPLAYER_FREEIF( demux_caps );
4766 parser = __mmplayer_element_create_and_link(player, srcpad, parser_name);
4768 MMPLAYER_FREEIF(parser_name);
4772 debug_error("failed to create parser\n");
4776 /* update srcpad if parser is created */
4777 pssrcpad = gst_element_get_static_pad(parser, "src");
4782 MMPLAYER_FREEIF(name);
4784 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
4787 debug_error("failed to create queue\n");
4791 /* update srcpad to link with decoder */
4792 qsrcpad = gst_element_get_static_pad(queue, "src");
4795 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
4797 /* assigning queue handle for futher manipulation purpose */
4798 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
4799 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
4801 mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
4802 mainbin[MMPLAYER_M_Q1].gst = queue;
4804 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
4806 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
4808 mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
4809 mainbin[MMPLAYER_M_Q2].gst = queue;
4811 g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
4815 debug_critical("Not supporting more then two elementary stream\n");
4819 pad = gst_element_get_static_pad(sinkelement, padname);
4823 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
4824 padname, GST_ELEMENT_NAME(sinkelement) );
4826 pad = gst_element_get_static_pad(sinkelement, "sink");
4829 debug_error("failed to get pad(sink) from %s. \n",
4830 GST_ELEMENT_NAME(sinkelement) );
4835 /* to check the video/audio type set the proper flag*/
4837 #ifdef GST_API_VERSION_1
4838 srccaps = gst_pad_get_current_caps( srcpad );
4840 srccaps = gst_pad_get_caps( srcpad );
4845 str = gst_caps_get_structure( srccaps, 0 );
4849 name = gst_structure_get_name(str);
4854 /* link queue and decoder. so, it will be queue - decoder. */
4855 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
4857 gst_object_unref(GST_OBJECT(pad));
4858 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
4860 /* reconstitute supportable codec */
4861 if (strstr(name, "video"))
4863 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
4865 else if (strstr(name, "audio"))
4867 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
4872 if (strstr(name, "video"))
4874 player->videodec_linked = 1;
4875 debug_msg("player->videodec_linked set to 1\n");
4878 else if (strstr(name, "audio"))
4880 player->audiodec_linked = 1;
4881 debug_msg("player->auddiodec_linked set to 1\n");
4884 gst_object_unref(GST_OBJECT(pad));
4885 gst_caps_unref(GST_CAPS(srccaps));
4889 if ( !MMPLAYER_IS_HTTP_PD(player) )
4891 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
4893 if (MMPLAYER_IS_HTTP_STREAMING(player))
4895 #ifndef GST_API_VERSION_1
4896 GstFormat fmt = GST_FORMAT_BYTES;
4898 gint64 dur_bytes = 0L;
4899 gchar *file_buffering_path = NULL;
4900 gboolean use_file_buffer = FALSE;
4902 if ( !mainbin[MMPLAYER_M_S_BUFFER].gst)
4904 debug_log("creating http streaming buffering queue\n");
4906 queue = gst_element_factory_make("queue2", "http_streaming_buffer");
4909 debug_critical ( "failed to create buffering queue element\n" );
4913 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
4915 debug_error("failed to set state READY to buffering queue\n");
4919 if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
4921 debug_error("failed to add buffering queue\n");
4925 qsinkpad = gst_element_get_static_pad(queue, "sink");
4926 qsrcpad = gst_element_get_static_pad(queue, "src");
4928 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
4930 debug_error("failed to link buffering queue\n");
4936 mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
4937 mainbin[MMPLAYER_M_S_BUFFER].gst = queue;
4939 if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
4941 #ifdef GST_API_VERSION_1
4942 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
4943 debug_error("fail to get duration.\n");
4945 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
4946 debug_error("fail to get duration.\n");
4951 use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
4952 file_buffering_path = g_strdup(PLAYER_INI()->http_file_buffer_path);
4956 __mm_player_streaming_set_buffer(player->streamer,
4959 PLAYER_INI()->http_max_size_bytes,
4961 PLAYER_INI()->http_buffering_limit,
4962 PLAYER_INI()->http_buffering_time,
4964 file_buffering_path,
4967 MMPLAYER_FREEIF(file_buffering_path);
4972 /* if it is not decoder or */
4973 /* in decoder case any of the video/audio still need to link*/
4974 if(!g_strrstr(klass, "Decoder"))
4977 pad = gst_element_get_static_pad(sinkelement, padname);
4980 debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
4981 padname, GST_ELEMENT_NAME(sinkelement) );
4983 pad = gst_element_get_static_pad(sinkelement, "sink");
4987 debug_error("failed to get pad(sink) from %s. \n",
4988 GST_ELEMENT_NAME(sinkelement) );
4993 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
4995 gst_object_unref(GST_OBJECT(pad));
4996 debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
5000 gst_object_unref(GST_OBJECT(pad));
5003 for(;templlist != NULL; templlist = templlist->next)
5005 padtemplate = templlist->data;
5007 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
5009 if( padtemplate->direction != GST_PAD_SRC ||
5010 padtemplate->presence == GST_PAD_REQUEST )
5013 switch(padtemplate->presence)
5015 case GST_PAD_ALWAYS:
5017 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
5018 #ifdef GST_API_VERSION_1
5019 GstCaps *caps = gst_pad_get_current_caps(srcpad);
5021 GstCaps *caps = gst_pad_get_caps(srcpad);
5024 /* Check whether caps has many types */
5025 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser")) {
5026 debug_log ("has_many_types for this caps [%s]\n", gst_caps_to_string(caps));
5027 has_many_types = TRUE;
5031 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
5033 gst_object_unref(GST_OBJECT(srcpad));
5034 gst_caps_unref(GST_CAPS(caps));
5036 debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
5040 gst_caps_unref(GST_CAPS(caps));
5041 gst_object_unref(GST_OBJECT(srcpad));
5047 case GST_PAD_SOMETIMES:
5048 has_dynamic_pads = TRUE;
5056 /* check if player can do start continually */
5057 MMPLAYER_CHECK_CMD_IF_EXIT(player);
5059 if( has_dynamic_pads )
5061 player->have_dynamic_pad = TRUE;
5062 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, "pad-added",
5063 G_CALLBACK(__mmplayer_add_new_pad), player);
5065 /* for streaming, more then one typefind will used for each elementary stream
5066 * so this doesn't mean the whole pipeline completion
5068 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
5070 MMPLAYER_SIGNAL_CONNECT( player, sinkelement, "no-more-pads",
5071 G_CALLBACK(__mmplayer_pipeline_complete), player);
5079 player->has_many_types = has_many_types;
5081 pad = gst_element_get_static_pad(sinkelement, "src");
5082 MMPLAYER_SIGNAL_CONNECT (player, pad, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
5083 gst_object_unref (GST_OBJECT(pad));
5087 /* check if player can do start continually */
5088 MMPLAYER_CHECK_CMD_IF_EXIT(player);
5090 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
5092 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
5098 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
5100 debug_error("failed to set state PAUSED to queue\n");
5106 gst_object_unref (GST_OBJECT(qsrcpad));
5112 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
5114 debug_error("failed to set state PAUSED to queue\n");
5120 gst_object_unref (GST_OBJECT(pssrcpad));
5132 gst_object_unref(GST_OBJECT(qsrcpad));
5134 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
5135 * You need to explicitly set elements to the NULL state before
5136 * dropping the final reference, to allow them to clean up.
5138 gst_element_set_state(queue, GST_STATE_NULL);
5139 /* And, it still has a parent "player".
5140 * You need to let the parent manage the object instead of unreffing the object directly.
5143 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
5144 //gst_object_unref( queue );
5148 gst_caps_unref(GST_CAPS(srccaps));
5153 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
5156 //const gchar *name;
5158 /* we only care about element factories */
5159 if (!GST_IS_ELEMENT_FACTORY(feature))
5162 /* only parsers, demuxers and decoders */
5163 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
5164 //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
5166 if( g_strrstr(klass, "Demux") == NULL &&
5167 g_strrstr(klass, "Codec/Decoder") == NULL &&
5168 g_strrstr(klass, "Depayloader") == NULL &&
5169 g_strrstr(klass, "Parse") == NULL)
5177 static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
5179 mm_player_t* player = (mm_player_t*) data;
5180 GstCaps *caps = NULL;
5181 GstStructure *str = NULL;
5186 return_if_fail ( pad )
5187 return_if_fail ( unused )
5188 return_if_fail ( data )
5190 #ifdef GST_API_VERSION_1
5191 caps = gst_pad_get_current_caps(pad);
5193 caps = gst_pad_get_caps(pad);
5198 str = gst_caps_get_structure(caps, 0);
5202 name = gst_structure_get_name(str);
5205 debug_log("name=%s\n", name);
5207 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
5209 debug_error("failed to autoplug for type (%s)\n", name);
5210 gst_caps_unref(caps);
5214 gst_caps_unref(caps);
5216 __mmplayer_pipeline_complete( NULL, (gpointer)player );
5223 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
5227 const char *stream_type;
5228 gchar *version_field = NULL;
5232 return_if_fail ( player );
5233 return_if_fail ( caps );
5235 str = gst_caps_get_structure(caps, 0);
5239 stream_type = gst_structure_get_name(str);
5244 /* set unlinked mime type for downloadable codec */
5245 if (g_str_has_prefix(stream_type, "video/"))
5247 if (g_str_has_prefix(stream_type, "video/mpeg"))
5249 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
5250 version_field = MM_PLAYER_MPEG_VNAME;
5252 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
5254 gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
5255 version_field = MM_PLAYER_WMV_VNAME;
5258 else if (g_str_has_prefix(stream_type, "video/x-divx"))
5260 gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
5261 version_field = MM_PLAYER_DIVX_VNAME;
5266 player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
5270 player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
5273 else if (g_str_has_prefix(stream_type, "audio/"))
5275 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
5277 gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
5278 version_field = MM_PLAYER_MPEG_VNAME;
5280 else if (g_str_has_prefix(stream_type, "audio/x-wma"))
5282 gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
5283 version_field = MM_PLAYER_WMA_VNAME;
5288 player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
5292 player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
5299 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
5301 mm_player_t* player = (mm_player_t*) data;
5302 GstCaps *caps = NULL;
5303 GstStructure *str = NULL;
5307 return_if_fail ( player );
5308 return_if_fail ( pad );
5310 GST_OBJECT_LOCK (pad);
5311 #ifdef GST_API_VERSION_1
5312 if ((caps = gst_pad_get_current_caps (pad)))
5315 if ((caps = GST_PAD_CAPS(pad)))
5318 GST_OBJECT_UNLOCK (pad);
5322 #ifdef GST_API_VERSION_1
5323 caps = gst_pad_get_current_caps(pad);
5325 caps = gst_pad_get_caps(pad);
5327 if ( !caps ) return;
5330 //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
5332 str = gst_caps_get_structure(caps, 0);
5336 name = gst_structure_get_name(str);
5340 player->num_dynamic_pad++;
5341 debug_log("stream count inc : %d\n", player->num_dynamic_pad);
5343 /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
5344 * If want to play it, remove this code.
5346 if (g_strrstr(name, "application"))
5348 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
5350 /* If id3/ape tag comes, keep going */
5351 debug_log("application mime exception : id3/ape tag");
5355 /* Otherwise, we assume that this stream is subtile. */
5356 debug_log(" application mime type pad is closed.");
5360 else if (g_strrstr(name, "audio"))
5362 gint samplerate = 0, channels = 0;
5364 /* set stream information */
5365 /* if possible, set it here because the caps is not distrubed by resampler. */
5366 gst_structure_get_int (str, "rate", &samplerate);
5367 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
5369 gst_structure_get_int (str, "channels", &channels);
5370 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
5372 debug_log("audio samplerate : %d channels : %d", samplerate, channels);
5374 else if (g_strrstr(name, "video"))
5377 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
5379 /* don't make video because of not required */
5380 if (stype == MM_DISPLAY_SURFACE_NULL)
5382 debug_log("no video because it's not required");
5386 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
5389 if ( ! __mmplayer_try_to_plug(player, pad, caps) )
5391 debug_error("failed to autoplug for type (%s)", name);
5393 __mmplayer_set_unlinked_mime_type(player, caps);
5396 gst_caps_unref(caps);
5402 /* test API for tuning audio gain. this API should be
5403 * deprecated before the day of final release
5406 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
5408 mm_player_t* player = (mm_player_t*) hplayer;
5409 gint error = MM_ERROR_NONE;
5411 gboolean isMidi = FALSE;
5416 return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5417 return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
5419 debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
5420 player->profile.play_mode, volume.level[0], volume.level[1]);
5422 isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
5429 /* is it proper volume level? */
5430 for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
5432 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
5433 debug_log("Invalid Volume level!!!! \n");
5434 return MM_ERROR_INVALID_ARGUMENT;
5440 if ( player->pipeline->mainbin )
5442 GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
5444 if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
5446 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
5448 g_object_set(midi_element, "volume", volume.level[0], NULL);
5454 if ( player->pipeline->audiobin )
5456 GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
5458 /* Set to Avsysaudiosink element */
5462 gboolean mute = FALSE;
5463 vol_value = volume.level[0];
5465 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
5467 mute = (vol_value == 0)? TRUE:FALSE;
5469 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
5481 __mmplayer_can_extract_pcm( mm_player_t* player )
5483 MMHandleType attrs = 0;
5484 gboolean is_drm = FALSE;
5485 gboolean sound_extraction = FALSE;
5487 return_val_if_fail ( player, FALSE );
5489 attrs = MMPLAYER_GET_ATTRS(player);
5492 debug_error("fail to get attributes.");
5496 /* check file is drm or not */
5497 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
5499 /* get sound_extraction property */
5500 mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
5502 if ( ! sound_extraction || is_drm )
5504 debug_log("checking pcm extraction mode : %d, drm : %d", sound_extraction, is_drm);
5512 __mmplayer_cancel_delayed_eos( mm_player_t* player )
5516 return_if_fail( player );
5518 if ( player->eos_timer )
5520 g_source_remove( player->eos_timer );
5523 player->eos_timer = 0;
5531 __mmplayer_eos_timer_cb(gpointer u_data)
5533 mm_player_t* player = NULL;
5534 player = (mm_player_t*) u_data;
5538 return_val_if_fail( player, FALSE );
5541 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
5543 /* cleare timer id */
5544 player->eos_timer = 0;
5548 /* we are returning FALSE as we need only one posting */
5552 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
5554 gint antishock = FALSE;
5555 MMHandleType attrs = 0;
5559 return_if_fail ( player && player->pipeline );
5561 /* It should be passed for video only clip */
5562 if ( ! player->pipeline->audiobin )
5565 if ( ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink")) )
5567 attrs = MMPLAYER_GET_ATTRS(player);
5570 debug_error("fail to get attributes.\n");
5574 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
5576 debug_log("setting antishock as (%d)\n", antishock);
5578 if ( disable_by_force )
5580 debug_log("but, antishock is disabled by force when is seeked\n");
5585 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
5593 /* Note : if silent is true, then subtitle would not be displayed. :*/
5594 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
5596 mm_player_t* player = (mm_player_t*) hplayer;
5600 /* check player handle */
5601 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5603 player->is_subtitle_off = silent;
5605 debug_log("subtitle is %s.\n", player->is_subtitle_off ? "ON" : "OFF");
5609 return MM_ERROR_NONE;
5613 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
5615 mm_player_t* player = (mm_player_t*) hplayer;
5619 /* check player handle */
5620 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5622 *silent = player->is_subtitle_off;
5624 debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
5628 return MM_ERROR_NONE;
5631 int _mmplayer_get_track_count(MMHandleType hplayer, MMPlayerTrackType track_type, int *count)
5633 mm_player_t* player = (mm_player_t*) hplayer;
5634 MMHandleType attrs = 0;
5635 int ret = MM_ERROR_NONE;
5639 /* check player handle */
5640 return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5641 return_val_if_fail(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
5642 return_val_if_fail((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
5643 ||(MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING),
5644 MM_ERROR_PLAYER_INVALID_STATE);
5646 attrs = MMPLAYER_GET_ATTRS(player);
5649 debug_error("cannot get content attribute");
5650 return MM_ERROR_PLAYER_INTERNAL;
5655 case MM_PLAYER_TRACK_TYPE_AUDIO:
5656 ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
5658 case MM_PLAYER_TRACK_TYPE_VIDEO:
5659 ret = mm_attrs_get_int_by_name(attrs, "content_video_track_num", count);
5661 case MM_PLAYER_TRACK_TYPE_TEXT:
5662 ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
5665 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
5669 debug_log ("%d track num is %d\n", track_type, *count);
5677 __get_state_name ( int state )
5681 case MM_PLAYER_STATE_NULL:
5683 case MM_PLAYER_STATE_READY:
5685 case MM_PLAYER_STATE_PAUSED:
5687 case MM_PLAYER_STATE_PLAYING:
5689 case MM_PLAYER_STATE_NONE: