4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
7 * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 /*===========================================================================================
27 ========================================================================================== */
30 #include <mm_attrs_private.h>
32 #include "mm_player_priv.h"
33 #include "mm_player_attrs.h"
34 #include "mm_player_utils.h"
36 /*===========================================================================================
38 | LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
40 ========================================================================================== */
42 /*---------------------------------------------------------------------------
43 | GLOBAL CONSTANT DEFINITIONS: |
44 ---------------------------------------------------------------------------*/
46 /*---------------------------------------------------------------------------
47 | IMPORTED VARIABLE DECLARATIONS: |
48 ---------------------------------------------------------------------------*/
50 /*---------------------------------------------------------------------------
51 | IMPORTED FUNCTION DECLARATIONS: |
52 ---------------------------------------------------------------------------*/
54 /*---------------------------------------------------------------------------
56 ---------------------------------------------------------------------------*/
58 /*---------------------------------------------------------------------------
59 | LOCAL CONSTANT DEFINITIONS: |
60 ---------------------------------------------------------------------------*/
62 /*---------------------------------------------------------------------------
63 | LOCAL DATA TYPE DEFINITIONS: |
64 ---------------------------------------------------------------------------*/
66 /*---------------------------------------------------------------------------
67 | GLOBAL VARIABLE DEFINITIONS: |
68 ---------------------------------------------------------------------------*/
70 /*---------------------------------------------------------------------------
71 | LOCAL VARIABLE DEFINITIONS: |
72 ---------------------------------------------------------------------------*/
74 /*---------------------------------------------------------------------------
75 | LOCAL FUNCTION PROTOTYPES: |
76 ---------------------------------------------------------------------------*/
77 static gint __gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error);
79 /*===========================================================================================
81 | FUNCTION DEFINITIONS |
83 ========================================================================================== */
85 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
87 MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
88 MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
90 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
92 //LOGD("incomming command : %d \n", command);
94 current_state = MMPLAYER_CURRENT_STATE(player);
95 pending_state = MMPLAYER_PENDING_STATE(player);
97 MMPLAYER_PRINT_STATE(player);
100 case MMPLAYER_COMMAND_CREATE:
102 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
104 if (current_state == MM_PLAYER_STATE_NULL ||
105 current_state == MM_PLAYER_STATE_READY ||
106 current_state == MM_PLAYER_STATE_PAUSED ||
107 current_state == MM_PLAYER_STATE_PLAYING)
112 case MMPLAYER_COMMAND_DESTROY:
114 /* destroy can called anytime */
116 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
120 case MMPLAYER_COMMAND_REALIZE:
122 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
124 if (pending_state != MM_PLAYER_STATE_NONE) {
127 /* need ready state to realize */
128 if (current_state == MM_PLAYER_STATE_READY)
131 if (current_state != MM_PLAYER_STATE_NULL)
137 case MMPLAYER_COMMAND_UNREALIZE:
139 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
141 if (current_state == MM_PLAYER_STATE_NULL)
146 case MMPLAYER_COMMAND_START:
148 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
150 if (pending_state == MM_PLAYER_STATE_NONE) {
151 if (current_state == MM_PLAYER_STATE_PLAYING)
153 else if (current_state != MM_PLAYER_STATE_READY &&
154 current_state != MM_PLAYER_STATE_PAUSED)
156 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
158 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
159 LOGD("player is going to paused state, just change the pending state as playing");
165 case MMPLAYER_COMMAND_STOP:
167 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
169 if (current_state == MM_PLAYER_STATE_READY)
172 /* need playing/paused state to stop */
173 if (current_state != MM_PLAYER_STATE_PLAYING &&
174 current_state != MM_PLAYER_STATE_PAUSED)
179 case MMPLAYER_COMMAND_PAUSE:
181 if (MMPLAYER_IS_LIVE_STREAMING(player))
184 if (player->doing_seek)
185 goto NOT_COMPLETED_SEEK;
187 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
189 if (pending_state == MM_PLAYER_STATE_NONE) {
190 if (current_state == MM_PLAYER_STATE_PAUSED)
192 else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of broswer
194 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
196 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
197 if (current_state == MM_PLAYER_STATE_PAUSED)
198 LOGD("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
205 case MMPLAYER_COMMAND_RESUME:
208 if (player->doing_seek)
209 goto NOT_COMPLETED_SEEK;
211 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
213 if (pending_state == MM_PLAYER_STATE_NONE) {
214 if (current_state == MM_PLAYER_STATE_PLAYING)
216 else if (current_state != MM_PLAYER_STATE_PAUSED)
218 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
220 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
221 LOGD("player is going to paused state, just change the pending state as playing");
230 player->cmd = command;
232 return MM_ERROR_NONE;
235 LOGW("since player is in wrong state(%s). it's not able to apply the command(%d)",
236 MMPLAYER_STATE_GET_NAME(current_state), command);
237 return MM_ERROR_PLAYER_INVALID_STATE;
240 LOGW("not completed seek");
241 return MM_ERROR_PLAYER_DOING_SEEK;
244 LOGW("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
245 return MM_ERROR_PLAYER_NO_OP;
248 LOGW("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
249 return MM_ERROR_PLAYER_NO_OP;
253 __mmplayer_gst_set_state(mm_player_t* player, GstElement * element, GstState state, gboolean async, gint timeout)
255 GstState element_state = GST_STATE_VOID_PENDING;
256 GstState element_pending_state = GST_STATE_VOID_PENDING;
257 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
261 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
262 MMPLAYER_RETURN_VAL_IF_FAIL(element, MM_ERROR_INVALID_ARGUMENT);
264 LOGD("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
267 ret = gst_element_set_state(element, state);
269 if (ret == GST_STATE_CHANGE_FAILURE) {
270 LOGE("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
272 /* dump state of all element */
273 __mmplayer_dump_pipeline_state(player);
275 return MM_ERROR_PLAYER_INTERNAL;
278 /* return here so state transition to be done in async mode */
280 LOGD("async state transition. not waiting for state complete.\n");
281 return MM_ERROR_NONE;
284 /* wait for state transition */
285 ret = gst_element_get_state(element, &element_state, &element_pending_state, timeout * GST_SECOND);
287 if (ret == GST_STATE_CHANGE_FAILURE || (state != element_state)) {
288 LOGE("failed to change [%s] element state to [%s] within %d sec\n",
289 GST_ELEMENT_NAME(element),
290 gst_element_state_get_name(state), timeout);
292 LOGE(" [%s] state : %s pending : %s \n",
293 GST_ELEMENT_NAME(element),
294 gst_element_state_get_name(element_state),
295 gst_element_state_get_name(element_pending_state));
297 /* dump state of all element */
298 __mmplayer_dump_pipeline_state(player);
300 return MM_ERROR_PLAYER_INTERNAL;
303 LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
307 return MM_ERROR_NONE;
310 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
312 GSource *source = NULL;
316 source = g_main_context_find_source_by_id(context, source_id);
318 if (source != NULL) {
319 LOGW("context: %p, source id: %d, source: %p", context, source_id, source);
320 g_source_destroy(source);
327 __mmplayer_dump_pipeline_state(mm_player_t* player)
329 GstIterator*iter = NULL;
330 gboolean done = FALSE;
333 GstElement *element = NULL;
334 GstElementFactory *factory = NULL;
336 GstState state = GST_STATE_VOID_PENDING;
337 GstState pending = GST_STATE_VOID_PENDING;
338 GstClockTime time = 200*GST_MSECOND;
342 MMPLAYER_RETURN_VAL_IF_FAIL(player &&
344 player->pipeline->mainbin,
347 iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
351 switch (gst_iterator_next(iter, &item)) {
352 case GST_ITERATOR_OK:
353 element = g_value_get_object(&item);
354 gst_element_get_state(element, &state, &pending, time);
356 factory = gst_element_get_factory(element) ;
358 LOGE("%s:%s : From:%s To:%s refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
359 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
360 g_value_reset(&item);
362 case GST_ITERATOR_RESYNC:
363 gst_iterator_resync(iter);
365 case GST_ITERATOR_ERROR:
368 case GST_ITERATOR_DONE:
375 element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
377 gst_element_get_state(element, &state, &pending, time);
379 factory = gst_element_get_factory(element) ;
382 LOGE("%s:%s : From:%s To:%s refcount : %d\n",
383 GST_OBJECT_NAME(factory),
384 GST_ELEMENT_NAME(element),
385 gst_element_state_get_name(state),
386 gst_element_state_get_name(pending),
387 GST_OBJECT_REFCOUNT_VALUE(element));
390 g_value_unset(&item);
393 gst_iterator_free(iter);
401 __get_state_name(int state)
404 case MM_PLAYER_STATE_NULL:
406 case MM_PLAYER_STATE_READY:
408 case MM_PLAYER_STATE_PAUSED:
410 case MM_PLAYER_STATE_PLAYING:
412 case MM_PLAYER_STATE_NONE:
420 __is_rtsp_streaming(mm_player_t* player)
422 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
424 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP) ? TRUE : FALSE;
428 __is_http_streaming(mm_player_t* player)
430 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
432 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP) ? TRUE : FALSE;
436 __is_streaming(mm_player_t* player)
438 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
440 return (__is_http_progressive_down(player) || __is_rtsp_streaming(player) || __is_http_streaming(player)
441 || __is_http_live_streaming(player) || __is_dash_streaming(player) || __is_smooth_streaming(player)) ? TRUE : FALSE;
445 __is_live_streaming(mm_player_t* player)
447 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
449 return (__is_rtsp_streaming(player) && player->streaming_type == STREAMING_SERVICE_LIVE) ? TRUE : FALSE;
453 __is_http_live_streaming(mm_player_t* player)
455 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
457 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ? TRUE : FALSE;
461 __is_dash_streaming(mm_player_t* player)
463 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
465 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH) ? TRUE : FALSE;
469 __is_smooth_streaming(mm_player_t* player)
471 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
473 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) ? TRUE : FALSE;
478 __is_http_progressive_down(mm_player_t* player)
480 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
482 return ((player->pd_mode) ? TRUE : FALSE);
485 /* if retval is FALSE, it will be dropped for perfomance. */
487 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
489 gboolean retval = FALSE;
491 if (!(player->pipeline && player->pipeline->mainbin)) {
492 LOGE("player pipeline handle is null");
496 switch (GST_MESSAGE_TYPE(message)) {
497 case GST_MESSAGE_TAG:
498 case GST_MESSAGE_EOS:
499 case GST_MESSAGE_ERROR:
500 case GST_MESSAGE_WARNING:
501 case GST_MESSAGE_CLOCK_LOST:
502 case GST_MESSAGE_NEW_CLOCK:
503 case GST_MESSAGE_ELEMENT:
504 case GST_MESSAGE_DURATION_CHANGED:
505 case GST_MESSAGE_ASYNC_START:
508 case GST_MESSAGE_ASYNC_DONE:
509 case GST_MESSAGE_STATE_CHANGED:
510 /* we only handle messages from pipeline */
511 if ((message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) && (!player->gapless.reconfigure))
516 case GST_MESSAGE_BUFFERING:
518 gint buffer_percent = 0;
521 gst_message_parse_buffering(message, &buffer_percent);
522 if (buffer_percent != MAX_BUFFER_PERCENT) {
523 LOGD("[%s] buffering msg %d%%!!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), buffer_percent);
527 if (!MMPLAYER_CMD_TRYLOCK(player)) {
528 LOGW("can't get cmd lock, send msg to bus");
532 if ((player->streamer) && (player->streamer->is_buffering == TRUE)) {
533 LOGD("[%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
534 player->streamer->is_buffering_done = TRUE;
537 MMPLAYER_CMD_UNLOCK(player);
550 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param)
552 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
557 //LOGD("Message (type : %d) will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
559 player->msg_cb(msgtype, param, player->msg_cb_param);
565 __mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* error)
567 MMMessageParamType msg_param;
568 gchar *msg_src_element;
572 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
573 MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
575 /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
577 memset(&msg_param, 0, sizeof(MMMessageParamType));
579 if (error->domain == GST_CORE_ERROR) {
580 msg_param.code = __gst_handle_core_error(player, error->code);
581 } else if (error->domain == GST_LIBRARY_ERROR) {
582 msg_param.code = __gst_handle_library_error(player, error->code);
583 } else if (error->domain == GST_RESOURCE_ERROR) {
584 msg_param.code = __gst_handle_resource_error(player, error->code, message);
585 } else if (error->domain == GST_STREAM_ERROR) {
586 msg_param.code = __gst_handle_stream_error(player, error, message);
588 LOGW("This error domain is not defined.\n");
590 /* we treat system error as an internal error */
591 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
595 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
597 msg_param.data = (void *) error->message;
599 LOGE("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
600 msg_src_element, g_quark_to_string(error->domain), error->message, error->code, msg_param.code);
604 if (msg_param.code == MM_ERROR_NONE)
607 /* skip error to avoid duplicated posting */
608 if ((player->storage_info[MMPLAYER_PATH_VOD].state <= STORAGE_STATE_REMOVED) ||
609 (player->storage_info[MMPLAYER_PATH_TEXT].state <= STORAGE_STATE_REMOVED)) {
611 /* The error will be handled by mused.
612 * @ref _mmplayer_manage_external_storage_state() */
614 LOGW("storage is removed, skip error post");
618 /* post error to application */
619 if (!player->msg_posted) {
620 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
621 /* don't post more if one was sent already */
622 player->msg_posted = TRUE;
624 LOGD("skip error post because it's sent already.\n");
632 __gst_handle_core_error(mm_player_t* player, int code)
634 gint trans_err = MM_ERROR_NONE;
638 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
641 case GST_CORE_ERROR_MISSING_PLUGIN:
642 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
643 case GST_CORE_ERROR_STATE_CHANGE:
644 case GST_CORE_ERROR_SEEK:
645 case GST_CORE_ERROR_NOT_IMPLEMENTED:
646 case GST_CORE_ERROR_FAILED:
647 case GST_CORE_ERROR_TOO_LAZY:
648 case GST_CORE_ERROR_PAD:
649 case GST_CORE_ERROR_THREAD:
650 case GST_CORE_ERROR_NEGOTIATION:
651 case GST_CORE_ERROR_EVENT:
652 case GST_CORE_ERROR_CAPS:
653 case GST_CORE_ERROR_TAG:
654 case GST_CORE_ERROR_CLOCK:
655 case GST_CORE_ERROR_DISABLED:
657 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
667 __gst_handle_library_error(mm_player_t* player, int code)
669 gint trans_err = MM_ERROR_NONE;
673 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
676 case GST_LIBRARY_ERROR_FAILED:
677 case GST_LIBRARY_ERROR_TOO_LAZY:
678 case GST_LIBRARY_ERROR_INIT:
679 case GST_LIBRARY_ERROR_SHUTDOWN:
680 case GST_LIBRARY_ERROR_SETTINGS:
681 case GST_LIBRARY_ERROR_ENCODE:
683 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
693 __gst_handle_resource_error(mm_player_t* player, int code, GstMessage * message)
695 gint trans_err = MM_ERROR_NONE;
699 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
702 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
703 trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
705 case GST_RESOURCE_ERROR_NOT_FOUND:
706 case GST_RESOURCE_ERROR_OPEN_READ:
707 if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
708 || MMPLAYER_IS_RTSP_STREAMING(player)) {
709 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
712 case GST_RESOURCE_ERROR_READ:
713 if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
714 || MMPLAYER_IS_RTSP_STREAMING(player)) {
715 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
717 } else if (message != NULL && message->src != NULL) {
718 storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
719 MMPlayerPathType path_type = MMPLAYER_PATH_MAX;
721 if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)
722 path_type = MMPLAYER_PATH_VOD;
723 else if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SUBSRC].gst)
724 path_type = MMPLAYER_PATH_TEXT;
726 if (path_type != MMPLAYER_PATH_MAX && player->storage_info[path_type].type == STORAGE_TYPE_EXTERNAL) {
727 /* check storage state */
728 storage_get_state(player->storage_info[path_type].id, &storage_state);
729 player->storage_info[path_type].state = storage_state;
730 LOGW("path %d, storage state %d:%d", path_type, player->storage_info[path_type].id, storage_state);
733 case GST_RESOURCE_ERROR_WRITE:
734 case GST_RESOURCE_ERROR_FAILED:
735 case GST_RESOURCE_ERROR_SEEK:
736 case GST_RESOURCE_ERROR_TOO_LAZY:
737 case GST_RESOURCE_ERROR_BUSY:
738 case GST_RESOURCE_ERROR_OPEN_WRITE:
739 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
740 case GST_RESOURCE_ERROR_CLOSE:
741 case GST_RESOURCE_ERROR_SYNC:
742 case GST_RESOURCE_ERROR_SETTINGS:
744 trans_err = MM_ERROR_PLAYER_INTERNAL;
754 __gst_handle_stream_error(mm_player_t* player, GError* error, GstMessage * message)
756 gint trans_err = MM_ERROR_NONE;
760 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
761 MMPLAYER_RETURN_VAL_IF_FAIL(error, MM_ERROR_INVALID_ARGUMENT);
762 MMPLAYER_RETURN_VAL_IF_FAIL(message, MM_ERROR_INVALID_ARGUMENT);
764 switch (error->code) {
765 case GST_STREAM_ERROR_FAILED:
766 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
767 case GST_STREAM_ERROR_DECODE:
768 case GST_STREAM_ERROR_WRONG_TYPE:
769 case GST_STREAM_ERROR_DECRYPT:
770 case GST_STREAM_ERROR_DECRYPT_NOKEY:
771 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
772 trans_err = __gst_transform_gsterror(player, message, error);
775 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
776 case GST_STREAM_ERROR_TOO_LAZY:
777 case GST_STREAM_ERROR_ENCODE:
778 case GST_STREAM_ERROR_DEMUX:
779 case GST_STREAM_ERROR_MUX:
780 case GST_STREAM_ERROR_FORMAT:
782 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
791 /* NOTE : decide gstreamer state whether there is some playable track or not. */
793 __gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error)
795 gchar *src_element_name = NULL;
796 GstElement *src_element = NULL;
797 GstElementFactory *factory = NULL;
798 const gchar* klass = NULL;
802 MMPLAYER_RETURN_VAL_IF_FAIL(message, MM_ERROR_INVALID_ARGUMENT);
803 MMPLAYER_RETURN_VAL_IF_FAIL(message->src, MM_ERROR_INVALID_ARGUMENT);
804 MMPLAYER_RETURN_VAL_IF_FAIL(error, MM_ERROR_INVALID_ARGUMENT);
805 MMPLAYER_RETURN_VAL_IF_FAIL(player &&
807 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
809 src_element = GST_ELEMENT_CAST(message->src);
813 src_element_name = GST_ELEMENT_NAME(src_element);
814 if (!src_element_name)
817 factory = gst_element_get_factory(src_element);
821 klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
825 LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
826 error->code, error->message, src_element_name, klass);
828 /* check whether the error is posted from not-activated track or not */
829 if (player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst) {
831 gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
832 LOGD("current active pad index -%d", active_pad_index);
834 if (src_element_name) {
837 if (player->audio_decoders) {
838 GList *adec = player->audio_decoders;
839 for (; adec ; adec = g_list_next(adec)) {
840 gchar *name = adec->data;
842 LOGD("found audio decoder name = %s", name);
843 if (g_strrstr(name, src_element_name)) {
850 LOGD("active pad = %d, error src index = %d", active_pad_index, msg_src_pos);
853 if (active_pad_index != msg_src_pos) {
854 LOGD("skip error because error is posted from no activated track");
855 return MM_ERROR_NONE;
859 switch (error->code) {
860 case GST_STREAM_ERROR_DECODE:
862 /* Demuxer can't parse one track because it's corrupted.
863 * So, the decoder for it is not linked.
864 * But, it has one playable track.
866 if (g_strrstr(klass, "Demux")) {
867 if (player->can_support_codec == FOUND_PLUGIN_VIDEO) {
868 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
869 } else if (player->can_support_codec == FOUND_PLUGIN_AUDIO) {
870 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
872 if (player->pipeline->audiobin) // PCM
873 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
875 goto CODEC_NOT_FOUND;
878 return MM_ERROR_PLAYER_INVALID_STREAM;
882 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
883 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
884 case GST_STREAM_ERROR_WRONG_TYPE:
886 if (src_element == player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst) {
887 LOGE("Not supported subtitle.");
888 return MM_ERROR_PLAYER_NOT_SUPPORTED_SUBTITLE;
890 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
893 case GST_STREAM_ERROR_FAILED:
895 /* Decoder Custom Message */
896 if (strstr(error->message, "ongoing")) {
897 if (strncasecmp(klass, "audio", 5)) {
898 if ((player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
899 LOGD("Video can keep playing.\n");
900 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
902 goto CODEC_NOT_FOUND;
904 } else if (strncasecmp(klass, "video", 5)) {
905 if ((player->can_support_codec & FOUND_PLUGIN_AUDIO)) {
906 LOGD("Audio can keep playing.\n");
907 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
909 goto CODEC_NOT_FOUND;
912 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
916 case GST_STREAM_ERROR_DECRYPT:
917 case GST_STREAM_ERROR_DECRYPT_NOKEY:
919 LOGE("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
921 if (strstr(error->message, "rights expired"))
922 return MM_ERROR_PLAYER_DRM_EXPIRED;
923 else if (strstr(error->message, "no rights"))
924 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
925 else if (strstr(error->message, "has future rights"))
926 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
927 else if (strstr(error->message, "opl violation"))
928 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
929 return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
939 return MM_ERROR_PLAYER_INVALID_STREAM;
942 return MM_ERROR_PLAYER_INTERNAL;
945 LOGD("not found any available codec. Player should be destroyed.\n");
946 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
950 __mmplayer_get_video_angle(mm_player_t* player, int *user_angle, int *org_angle)
952 int user_angle_type = 0;
953 gchar *org_orient = NULL;
954 MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
957 LOGE("cannot get content attribute");
958 return MM_ERROR_PLAYER_INTERNAL;
961 /* update user roation */
962 mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
964 /* get angle with user type */
965 switch (user_angle_type) {
966 case MM_DISPLAY_ROTATION_NONE:
969 case MM_DISPLAY_ROTATION_90: /* counter-clockwise 90 */
972 case MM_DISPLAY_ROTATION_180:
975 case MM_DISPLAY_ROTATION_270: /* clockwise 90 */
980 /* get original orientation */
981 mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
984 if (!strcmp(org_orient, "rotate-90"))
986 else if (!strcmp(org_orient, "rotate-180"))
988 else if (!strcmp(org_orient, "rotate-270"))
991 LOGD("original rotation is %s", org_orient);
993 LOGD("content_video_orientation get fail");
995 LOGD("check user angle: %d, orientation: %d", *user_angle, *org_angle);
997 return MM_ERROR_NONE;