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 ========================================================================================== */
28 #include <gst/wayland/wayland.h>
29 #include <gst/video/videooverlay.h>
33 #include <mm_attrs_private.h>
35 #include "mm_player_priv.h"
36 #include "mm_player_attrs.h"
37 #include "mm_player_utils.h"
39 /*===========================================================================================
41 | LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
43 ========================================================================================== */
45 /*---------------------------------------------------------------------------
46 | GLOBAL CONSTANT DEFINITIONS: |
47 ---------------------------------------------------------------------------*/
49 /*---------------------------------------------------------------------------
50 | IMPORTED VARIABLE DECLARATIONS: |
51 ---------------------------------------------------------------------------*/
53 /*---------------------------------------------------------------------------
54 | IMPORTED FUNCTION DECLARATIONS: |
55 ---------------------------------------------------------------------------*/
57 /*---------------------------------------------------------------------------
59 ---------------------------------------------------------------------------*/
61 /*---------------------------------------------------------------------------
62 | LOCAL CONSTANT DEFINITIONS: |
63 ---------------------------------------------------------------------------*/
65 /*---------------------------------------------------------------------------
66 | LOCAL DATA TYPE DEFINITIONS: |
67 ---------------------------------------------------------------------------*/
69 /*---------------------------------------------------------------------------
70 | GLOBAL VARIABLE DEFINITIONS: |
71 ---------------------------------------------------------------------------*/
73 /*---------------------------------------------------------------------------
74 | LOCAL VARIABLE DEFINITIONS: |
75 ---------------------------------------------------------------------------*/
77 /*---------------------------------------------------------------------------
78 | LOCAL FUNCTION PROTOTYPES: |
79 ---------------------------------------------------------------------------*/
80 static gint __gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error);
82 /*===========================================================================================
84 | FUNCTION DEFINITIONS |
86 ========================================================================================== */
88 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
90 MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
91 MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
93 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
95 //LOGD("incomming command : %d \n", command);
97 current_state = MMPLAYER_CURRENT_STATE(player);
98 pending_state = MMPLAYER_PENDING_STATE(player);
100 MMPLAYER_PRINT_STATE(player);
103 case MMPLAYER_COMMAND_CREATE:
105 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
107 if (current_state == MM_PLAYER_STATE_NULL ||
108 current_state == MM_PLAYER_STATE_READY ||
109 current_state == MM_PLAYER_STATE_PAUSED ||
110 current_state == MM_PLAYER_STATE_PLAYING)
115 case MMPLAYER_COMMAND_DESTROY:
117 /* destroy can called anytime */
119 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
123 case MMPLAYER_COMMAND_REALIZE:
125 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
127 if (pending_state != MM_PLAYER_STATE_NONE) {
130 /* need ready state to realize */
131 if (current_state == MM_PLAYER_STATE_READY)
134 if (current_state != MM_PLAYER_STATE_NULL)
140 case MMPLAYER_COMMAND_UNREALIZE:
142 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
144 if (current_state == MM_PLAYER_STATE_NULL)
149 case MMPLAYER_COMMAND_START:
151 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
153 if (pending_state == MM_PLAYER_STATE_NONE) {
154 if (current_state == MM_PLAYER_STATE_PLAYING)
156 else if (current_state != MM_PLAYER_STATE_READY &&
157 current_state != MM_PLAYER_STATE_PAUSED)
159 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
161 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
162 LOGD("player is going to paused state, just change the pending state as playing");
168 case MMPLAYER_COMMAND_STOP:
170 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
172 if (current_state == MM_PLAYER_STATE_READY)
175 /* need playing/paused state to stop */
176 if (current_state != MM_PLAYER_STATE_PLAYING &&
177 current_state != MM_PLAYER_STATE_PAUSED)
182 case MMPLAYER_COMMAND_PAUSE:
184 if (MMPLAYER_IS_LIVE_STREAMING(player))
187 if (player->doing_seek)
188 goto NOT_COMPLETED_SEEK;
190 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
192 if (pending_state == MM_PLAYER_STATE_NONE) {
193 if (current_state == MM_PLAYER_STATE_PAUSED)
195 else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of broswer
197 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
199 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
200 if (current_state == MM_PLAYER_STATE_PAUSED)
201 LOGD("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
208 case MMPLAYER_COMMAND_RESUME:
211 if (player->doing_seek)
212 goto NOT_COMPLETED_SEEK;
214 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
216 if (pending_state == MM_PLAYER_STATE_NONE) {
217 if (current_state == MM_PLAYER_STATE_PLAYING)
219 else if (current_state != MM_PLAYER_STATE_PAUSED)
221 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
223 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
224 LOGD("player is going to paused state, just change the pending state as playing");
233 player->cmd = command;
235 return MM_ERROR_NONE;
238 LOGW("since player is in wrong state(%s). it's not able to apply the command(%d)",
239 MMPLAYER_STATE_GET_NAME(current_state), command);
240 return MM_ERROR_PLAYER_INVALID_STATE;
243 LOGW("not completed seek");
244 return MM_ERROR_PLAYER_DOING_SEEK;
247 LOGW("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
248 return MM_ERROR_PLAYER_NO_OP;
251 LOGW("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
252 return MM_ERROR_PLAYER_NO_OP;
256 __mmplayer_gst_set_state(mm_player_t* player, GstElement * element, GstState state, gboolean async, gint timeout)
258 GstState element_state = GST_STATE_VOID_PENDING;
259 GstState element_pending_state = GST_STATE_VOID_PENDING;
260 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
264 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
265 MMPLAYER_RETURN_VAL_IF_FAIL(element, MM_ERROR_INVALID_ARGUMENT);
267 LOGD("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
270 ret = gst_element_set_state(element, state);
272 if (ret == GST_STATE_CHANGE_FAILURE) {
273 LOGE("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
275 /* dump state of all element */
276 __mmplayer_dump_pipeline_state(player);
278 return MM_ERROR_PLAYER_INTERNAL;
281 /* return here so state transition to be done in async mode */
283 LOGD("async state transition. not waiting for state complete.\n");
284 return MM_ERROR_NONE;
287 /* wait for state transition */
288 ret = gst_element_get_state(element, &element_state, &element_pending_state, timeout * GST_SECOND);
290 if (ret == GST_STATE_CHANGE_FAILURE || (state != element_state)) {
291 LOGE("failed to change [%s] element state to [%s] within %d sec\n",
292 GST_ELEMENT_NAME(element),
293 gst_element_state_get_name(state), timeout);
295 LOGE(" [%s] state : %s pending : %s \n",
296 GST_ELEMENT_NAME(element),
297 gst_element_state_get_name(element_state),
298 gst_element_state_get_name(element_pending_state));
300 /* dump state of all element */
301 __mmplayer_dump_pipeline_state(player);
303 return MM_ERROR_PLAYER_INTERNAL;
306 LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
310 return MM_ERROR_NONE;
313 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
315 GSource *source = NULL;
319 source = g_main_context_find_source_by_id(context, source_id);
321 if (source != NULL) {
322 LOGW("context: %p, source id: %d, source: %p", context, source_id, source);
323 g_source_destroy(source);
330 __mmplayer_dump_pipeline_state(mm_player_t* player)
332 GstIterator*iter = NULL;
333 gboolean done = FALSE;
336 GstElement *element = NULL;
337 GstElementFactory *factory = NULL;
339 GstState state = GST_STATE_VOID_PENDING;
340 GstState pending = GST_STATE_VOID_PENDING;
341 GstClockTime time = 200*GST_MSECOND;
345 MMPLAYER_RETURN_VAL_IF_FAIL(player &&
347 player->pipeline->mainbin,
350 iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
354 switch (gst_iterator_next(iter, &item)) {
355 case GST_ITERATOR_OK:
356 element = g_value_get_object(&item);
357 gst_element_get_state(element, &state, &pending, time);
359 factory = gst_element_get_factory(element) ;
361 LOGE("%s:%s : From:%s To:%s refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
362 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
363 g_value_reset(&item);
365 case GST_ITERATOR_RESYNC:
366 gst_iterator_resync(iter);
368 case GST_ITERATOR_ERROR:
371 case GST_ITERATOR_DONE:
378 element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
380 gst_element_get_state(element, &state, &pending, time);
382 factory = gst_element_get_factory(element) ;
385 LOGE("%s:%s : From:%s To:%s refcount : %d\n",
386 GST_OBJECT_NAME(factory),
387 GST_ELEMENT_NAME(element),
388 gst_element_state_get_name(state),
389 gst_element_state_get_name(pending),
390 GST_OBJECT_REFCOUNT_VALUE(element));
393 g_value_unset(&item);
396 gst_iterator_free(iter);
404 __get_state_name(int state)
407 case MM_PLAYER_STATE_NULL:
409 case MM_PLAYER_STATE_READY:
411 case MM_PLAYER_STATE_PAUSED:
413 case MM_PLAYER_STATE_PLAYING:
415 case MM_PLAYER_STATE_NONE:
423 __is_rtsp_streaming(mm_player_t* player)
425 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
427 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP) ? TRUE : FALSE;
431 __is_wfd_streaming(mm_player_t* player)
433 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
435 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD) ? TRUE : FALSE;
439 __is_http_streaming(mm_player_t* player)
441 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
443 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP) ? TRUE : FALSE;
447 __is_streaming(mm_player_t* player)
449 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
451 return (__is_http_progressive_down(player) || __is_rtsp_streaming(player) || __is_wfd_streaming(player) || __is_http_streaming(player)
452 || __is_http_live_streaming(player) || __is_dash_streaming(player) || __is_smooth_streaming(player)) ? TRUE : FALSE;
456 __is_live_streaming(mm_player_t* player)
458 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
460 return (__is_rtsp_streaming(player) && player->streaming_type == STREAMING_SERVICE_LIVE) ? TRUE : FALSE;
464 __is_http_live_streaming(mm_player_t* player)
466 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
468 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ? TRUE : FALSE;
472 __is_dash_streaming(mm_player_t* player)
474 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
476 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH) ? TRUE : FALSE;
480 __is_smooth_streaming(mm_player_t* player)
482 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
484 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) ? TRUE : FALSE;
489 __is_http_progressive_down(mm_player_t* player)
491 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
493 return ((player->pd_mode) ? TRUE : FALSE);
496 /* if retval is FALSE, it will be dropped for perfomance. */
498 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
500 gboolean retval = FALSE;
502 if (!(player->pipeline && player->pipeline->mainbin)) {
503 LOGE("player pipeline handle is null");
507 switch (GST_MESSAGE_TYPE(message)) {
508 case GST_MESSAGE_TAG:
509 case GST_MESSAGE_EOS:
510 case GST_MESSAGE_ERROR:
511 case GST_MESSAGE_WARNING:
512 case GST_MESSAGE_CLOCK_LOST:
513 case GST_MESSAGE_NEW_CLOCK:
514 case GST_MESSAGE_ELEMENT:
515 case GST_MESSAGE_DURATION_CHANGED:
516 case GST_MESSAGE_ASYNC_START:
519 case GST_MESSAGE_ASYNC_DONE:
520 case GST_MESSAGE_STATE_CHANGED:
521 /* we only handle messages from pipeline */
522 if ((message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) && (!player->gapless.reconfigure))
527 case GST_MESSAGE_BUFFERING:
529 gint buffer_percent = 0;
531 gst_message_parse_buffering(message, &buffer_percent);
533 if ((MMPLAYER_IS_STREAMING(player)) &&
534 (player->streamer) &&
535 (player->streamer->is_buffering == TRUE) &&
536 (buffer_percent == MAX_BUFFER_PERCENT)) {
537 LOGD(">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
538 player->streamer->is_buffering_done = TRUE;
553 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param)
555 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
560 //LOGD("Message (type : %d) will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
562 player->msg_cb(msgtype, param, player->msg_cb_param);
568 __mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* error)
570 MMMessageParamType msg_param;
571 gchar *msg_src_element;
575 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
576 MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
578 /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
580 memset(&msg_param, 0, sizeof(MMMessageParamType));
582 if (error->domain == GST_CORE_ERROR) {
583 msg_param.code = __gst_handle_core_error(player, error->code);
584 } else if (error->domain == GST_LIBRARY_ERROR) {
585 msg_param.code = __gst_handle_library_error(player, error->code);
586 } else if (error->domain == GST_RESOURCE_ERROR) {
587 msg_param.code = __gst_handle_resource_error(player, error->code);
588 } else if (error->domain == GST_STREAM_ERROR) {
589 msg_param.code = __gst_handle_stream_error(player, error, message);
591 LOGW("This error domain is not defined.\n");
593 /* we treat system error as an internal error */
594 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
598 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
600 msg_param.data = (void *) error->message;
602 LOGE("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
603 msg_src_element, g_quark_to_string(error->domain), error->message, error->code, msg_param.code);
607 if (msg_param.code == MM_ERROR_NONE)
610 /* post error to application */
611 if (!player->msg_posted) {
612 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
613 /* don't post more if one was sent already */
614 player->msg_posted = TRUE;
616 LOGD("skip error post because it's sent already.\n");
624 __gst_handle_core_error(mm_player_t* player, int code)
626 gint trans_err = MM_ERROR_NONE;
630 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
633 case GST_CORE_ERROR_MISSING_PLUGIN:
634 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
635 case GST_CORE_ERROR_STATE_CHANGE:
636 case GST_CORE_ERROR_SEEK:
637 case GST_CORE_ERROR_NOT_IMPLEMENTED:
638 case GST_CORE_ERROR_FAILED:
639 case GST_CORE_ERROR_TOO_LAZY:
640 case GST_CORE_ERROR_PAD:
641 case GST_CORE_ERROR_THREAD:
642 case GST_CORE_ERROR_NEGOTIATION:
643 case GST_CORE_ERROR_EVENT:
644 case GST_CORE_ERROR_CAPS:
645 case GST_CORE_ERROR_TAG:
646 case GST_CORE_ERROR_CLOCK:
647 case GST_CORE_ERROR_DISABLED:
649 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
659 __gst_handle_library_error(mm_player_t* player, int code)
661 gint trans_err = MM_ERROR_NONE;
665 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
668 case GST_LIBRARY_ERROR_FAILED:
669 case GST_LIBRARY_ERROR_TOO_LAZY:
670 case GST_LIBRARY_ERROR_INIT:
671 case GST_LIBRARY_ERROR_SHUTDOWN:
672 case GST_LIBRARY_ERROR_SETTINGS:
673 case GST_LIBRARY_ERROR_ENCODE:
675 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
685 __gst_handle_resource_error(mm_player_t* player, int code)
687 gint trans_err = MM_ERROR_NONE;
691 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
694 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
695 trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
697 case GST_RESOURCE_ERROR_NOT_FOUND:
698 case GST_RESOURCE_ERROR_OPEN_READ:
699 if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
700 || MMPLAYER_IS_RTSP_STREAMING(player)) {
701 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
704 case GST_RESOURCE_ERROR_READ:
705 if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
706 || MMPLAYER_IS_RTSP_STREAMING(player)) {
707 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
710 case GST_RESOURCE_ERROR_WRITE:
711 case GST_RESOURCE_ERROR_FAILED:
712 case GST_RESOURCE_ERROR_SEEK:
713 case GST_RESOURCE_ERROR_TOO_LAZY:
714 case GST_RESOURCE_ERROR_BUSY:
715 case GST_RESOURCE_ERROR_OPEN_WRITE:
716 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
717 case GST_RESOURCE_ERROR_CLOSE:
718 case GST_RESOURCE_ERROR_SYNC:
719 case GST_RESOURCE_ERROR_SETTINGS:
721 trans_err = MM_ERROR_PLAYER_INTERNAL;
731 __gst_handle_stream_error(mm_player_t* player, GError* error, GstMessage * message)
733 gint trans_err = MM_ERROR_NONE;
737 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
738 MMPLAYER_RETURN_VAL_IF_FAIL(error, MM_ERROR_INVALID_ARGUMENT);
739 MMPLAYER_RETURN_VAL_IF_FAIL(message, MM_ERROR_INVALID_ARGUMENT);
741 switch (error->code) {
742 case GST_STREAM_ERROR_FAILED:
743 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
744 case GST_STREAM_ERROR_DECODE:
745 case GST_STREAM_ERROR_WRONG_TYPE:
746 case GST_STREAM_ERROR_DECRYPT:
747 case GST_STREAM_ERROR_DECRYPT_NOKEY:
748 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
749 trans_err = __gst_transform_gsterror(player, message, error);
752 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
753 case GST_STREAM_ERROR_TOO_LAZY:
754 case GST_STREAM_ERROR_ENCODE:
755 case GST_STREAM_ERROR_DEMUX:
756 case GST_STREAM_ERROR_MUX:
757 case GST_STREAM_ERROR_FORMAT:
759 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
768 /* NOTE : decide gstreamer state whether there is some playable track or not. */
770 __gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error)
772 gchar *src_element_name = NULL;
773 GstElement *src_element = NULL;
774 GstElementFactory *factory = NULL;
775 const gchar* klass = NULL;
779 MMPLAYER_RETURN_VAL_IF_FAIL(message, MM_ERROR_INVALID_ARGUMENT);
780 MMPLAYER_RETURN_VAL_IF_FAIL(message->src, MM_ERROR_INVALID_ARGUMENT);
781 MMPLAYER_RETURN_VAL_IF_FAIL(error, MM_ERROR_INVALID_ARGUMENT);
783 src_element = GST_ELEMENT_CAST(message->src);
787 src_element_name = GST_ELEMENT_NAME(src_element);
788 if (!src_element_name)
791 factory = gst_element_get_factory(src_element);
795 klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
799 LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
800 error->code, error->message, src_element_name, klass);
804 if (player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst) {
806 gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
807 LOGD("current active pad index -%d", active_pad_index);
809 if (src_element_name) {
812 if (player->audio_decoders) {
813 GList *adec = player->audio_decoders;
814 for (; adec ; adec = g_list_next(adec)) {
815 gchar *name = adec->data;
817 LOGD("found audio decoder name = %s", name);
818 if (g_strrstr(name, src_element_name)) {
825 LOGD("active pad = %d, error src index = %d", active_pad_index, msg_src_pos);
828 if (active_pad_index != msg_src_pos) {
829 LOGD("skip error because error is posted from no activated track");
830 return MM_ERROR_NONE;
834 //-> check!! if needed or not
836 switch (error->code) {
837 case GST_STREAM_ERROR_DECODE:
839 /* Demuxer can't parse one track because it's corrupted.
840 * So, the decoder for it is not linked.
841 * But, it has one playable track.
843 if (g_strrstr(klass, "Demux")) {
844 if (player->can_support_codec == FOUND_PLUGIN_VIDEO) {
845 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
846 } else if (player->can_support_codec == FOUND_PLUGIN_AUDIO) {
847 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
849 if (player->pipeline->audiobin) // PCM
850 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
852 goto CODEC_NOT_FOUND;
855 return MM_ERROR_PLAYER_INVALID_STREAM;
859 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
860 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
861 case GST_STREAM_ERROR_WRONG_TYPE:
862 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
864 case GST_STREAM_ERROR_FAILED:
866 /* Decoder Custom Message */
867 if (strstr(error->message, "ongoing")) {
868 if (strncasecmp(klass, "audio", 5)) {
869 if ((player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
870 LOGD("Video can keep playing.\n");
871 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
873 goto CODEC_NOT_FOUND;
875 } else if (strncasecmp(klass, "video", 5)) {
876 if ((player->can_support_codec & FOUND_PLUGIN_AUDIO)) {
877 LOGD("Audio can keep playing.\n");
878 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
880 goto CODEC_NOT_FOUND;
883 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
887 case GST_STREAM_ERROR_DECRYPT:
888 case GST_STREAM_ERROR_DECRYPT_NOKEY:
890 LOGE("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
892 if (strstr(error->message, "rights expired"))
893 return MM_ERROR_PLAYER_DRM_EXPIRED;
894 else if (strstr(error->message, "no rights"))
895 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
896 else if (strstr(error->message, "has future rights"))
897 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
898 else if (strstr(error->message, "opl violation"))
899 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
900 return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
910 return MM_ERROR_PLAYER_INVALID_STREAM;
913 return MM_ERROR_PLAYER_INTERNAL;
916 LOGD("not found any available codec. Player should be destroyed.\n");
917 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
921 __mmplayer_get_video_angle(mm_player_t* player, int *user_angle, int *org_angle)
923 int user_angle_type = 0;
924 gchar *org_orient = NULL;
925 MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
928 LOGE("cannot get content attribute");
929 return MM_ERROR_PLAYER_INTERNAL;
932 /* update user roation */
933 mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
935 /* get angle with user type */
936 switch (user_angle_type) {
937 case MM_DISPLAY_ROTATION_NONE:
940 case MM_DISPLAY_ROTATION_90: /* counter-clockwise 90 */
943 case MM_DISPLAY_ROTATION_180:
946 case MM_DISPLAY_ROTATION_270: /* clockwise 90 */
951 /* get original orientation */
952 mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
955 if (!strcmp(org_orient, "rotate-90"))
957 else if (!strcmp(org_orient, "rotate-180"))
959 else if (!strcmp(org_orient, "rotate-270"))
962 LOGD("original rotation is %s", org_orient);
964 LOGD("content_video_orientation get fail");
966 LOGD("check user angle: %d, orientation: %d", *user_angle, *org_angle);
968 return MM_ERROR_NONE;