Merge "Fixed SVACE critical issues" into tizen_3.0
[platform/core/multimedia/libmm-player.git] / src / mm_player_common_priv.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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>
8  *
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
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
21  */
22
23 /*===========================================================================================
24 |                                                                                                                                                                                       |
25 |  INCLUDE FILES                                                                                                                                                        |
26 |                                                                                                                                                                                       |
27 ========================================================================================== */
28 #include <gst/wayland/wayland.h>
29 #include <gst/video/videooverlay.h>
30
31 #include <dlog.h>
32 #include <mm_error.h>
33 #include <mm_attrs_private.h>
34
35 #include "mm_player_priv.h"
36 #include "mm_player_attrs.h"
37 #include "mm_player_utils.h"
38
39 /*===========================================================================================
40 |                                                                                                                                                                                       |
41 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
42 |                                                                                                                                                                                       |
43 ========================================================================================== */
44
45 /*---------------------------------------------------------------------------
46 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
47 ---------------------------------------------------------------------------*/
48
49 /*---------------------------------------------------------------------------
50 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
51 ---------------------------------------------------------------------------*/
52
53 /*---------------------------------------------------------------------------
54 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
55 ---------------------------------------------------------------------------*/
56
57 /*---------------------------------------------------------------------------
58 |    LOCAL #defines:                                                                                                            |
59 ---------------------------------------------------------------------------*/
60
61 /*---------------------------------------------------------------------------
62 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
63 ---------------------------------------------------------------------------*/
64
65 /*---------------------------------------------------------------------------
66 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
67 ---------------------------------------------------------------------------*/
68
69 /*---------------------------------------------------------------------------
70 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
71 ---------------------------------------------------------------------------*/
72
73 /*---------------------------------------------------------------------------
74 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
75 ---------------------------------------------------------------------------*/
76
77 /*---------------------------------------------------------------------------
78 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
79 ---------------------------------------------------------------------------*/
80 static gint __gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error);
81
82 /*===========================================================================================
83 |                                                                                                                                                                                       |
84 |  FUNCTION DEFINITIONS                                                                                                                                         |
85 |                                                                                                                                                                                       |
86 ========================================================================================== */
87 int
88 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
89 {
90         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
91         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
92
93         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
94
95         //LOGD("incomming command : %d \n", command);
96
97         current_state = MMPLAYER_CURRENT_STATE(player);
98         pending_state = MMPLAYER_PENDING_STATE(player);
99
100         MMPLAYER_PRINT_STATE(player);
101
102         switch (command) {
103         case MMPLAYER_COMMAND_CREATE:
104         {
105                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
106
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)
111                         goto NO_OP;
112         }
113         break;
114
115         case MMPLAYER_COMMAND_DESTROY:
116         {
117                 /* destroy can called anytime */
118
119                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
120         }
121         break;
122
123         case MMPLAYER_COMMAND_REALIZE:
124         {
125                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
126
127                 if (pending_state != MM_PLAYER_STATE_NONE) {
128                         goto INVALID_STATE;
129                 } else {
130                         /* need ready state to realize */
131                         if (current_state == MM_PLAYER_STATE_READY)
132                                 goto NO_OP;
133
134                         if (current_state != MM_PLAYER_STATE_NULL)
135                                 goto INVALID_STATE;
136                 }
137         }
138         break;
139
140         case MMPLAYER_COMMAND_UNREALIZE:
141         {
142                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
143
144                 if (current_state == MM_PLAYER_STATE_NULL)
145                         goto NO_OP;
146         }
147         break;
148
149         case MMPLAYER_COMMAND_START:
150         {
151                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
152
153                 if (pending_state == MM_PLAYER_STATE_NONE) {
154                         if (current_state == MM_PLAYER_STATE_PLAYING)
155                                 goto NO_OP;
156                         else if (current_state  != MM_PLAYER_STATE_READY &&
157                                 current_state != MM_PLAYER_STATE_PAUSED)
158                                 goto INVALID_STATE;
159                 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
160                         goto ALREADY_GOING;
161                 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
162                         LOGD("player is going to paused state, just change the pending state as playing");
163                 } else
164                         goto INVALID_STATE;
165         }
166         break;
167
168         case MMPLAYER_COMMAND_STOP:
169         {
170                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
171
172                 if (current_state == MM_PLAYER_STATE_READY)
173                         goto NO_OP;
174
175                 /* need playing/paused state to stop */
176                 if (current_state != MM_PLAYER_STATE_PLAYING &&
177                          current_state != MM_PLAYER_STATE_PAUSED)
178                         goto INVALID_STATE;
179         }
180         break;
181
182         case MMPLAYER_COMMAND_PAUSE:
183         {
184                 if (MMPLAYER_IS_LIVE_STREAMING(player))
185                         goto NO_OP;
186
187                 if (player->doing_seek)
188                         goto NOT_COMPLETED_SEEK;
189
190                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
191
192                 if (pending_state == MM_PLAYER_STATE_NONE) {
193                         if (current_state == MM_PLAYER_STATE_PAUSED)
194                                 goto NO_OP;
195                         else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of broswer
196                                 goto INVALID_STATE;
197                 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
198                         goto ALREADY_GOING;
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");
202                         else
203                                 goto INVALID_STATE;
204                 }
205         }
206         break;
207
208         case MMPLAYER_COMMAND_RESUME:
209         {
210
211                 if (player->doing_seek)
212                         goto NOT_COMPLETED_SEEK;
213
214                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
215
216                 if (pending_state == MM_PLAYER_STATE_NONE) {
217                         if (current_state == MM_PLAYER_STATE_PLAYING)
218                                 goto NO_OP;
219                         else if (current_state != MM_PLAYER_STATE_PAUSED)
220                                 goto INVALID_STATE;
221                 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
222                         goto ALREADY_GOING;
223                 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
224                         LOGD("player is going to paused state, just change the pending state as playing");
225                 } else
226                         goto INVALID_STATE;
227         }
228                 break;
229
230         default:
231                 break;
232         }
233         player->cmd = command;
234
235         return MM_ERROR_NONE;
236
237 INVALID_STATE:
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;
241
242 NOT_COMPLETED_SEEK:
243         LOGW("not completed seek");
244         return MM_ERROR_PLAYER_DOING_SEEK;
245
246 NO_OP:
247         LOGW("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
248         return MM_ERROR_PLAYER_NO_OP;
249
250 ALREADY_GOING:
251         LOGW("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
252         return MM_ERROR_PLAYER_NO_OP;
253 }
254
255 int
256 __mmplayer_gst_set_state(mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout)
257 {
258         GstState element_state = GST_STATE_VOID_PENDING;
259         GstState element_pending_state = GST_STATE_VOID_PENDING;
260         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
261
262         MMPLAYER_FENTER();
263
264         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
265         MMPLAYER_RETURN_VAL_IF_FAIL(element, MM_ERROR_INVALID_ARGUMENT);
266
267         LOGD("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
268
269         /* set state */
270         ret = gst_element_set_state(element, state);
271
272         if (ret == GST_STATE_CHANGE_FAILURE) {
273                 LOGE("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
274
275                 /* dump state of all element */
276                 __mmplayer_dump_pipeline_state(player);
277
278                 return MM_ERROR_PLAYER_INTERNAL;
279         }
280
281         /* return here so state transition to be done in async mode */
282         if (async) {
283                 LOGD("async state transition. not waiting for state complete.\n");
284                 return MM_ERROR_NONE;
285         }
286
287         /* wait for state transition */
288         ret = gst_element_get_state(element, &element_state, &element_pending_state, timeout * GST_SECOND);
289
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);
294
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));
299
300                 /* dump state of all element */
301                 __mmplayer_dump_pipeline_state(player);
302
303                 return MM_ERROR_PLAYER_INTERNAL;
304         }
305
306         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
307
308         MMPLAYER_FLEAVE();
309
310         return MM_ERROR_NONE;
311 }
312
313 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
314 {
315         GSource *source = NULL;
316
317         MMPLAYER_FENTER();
318
319         source = g_main_context_find_source_by_id(context, source_id);
320
321         if (source != NULL) {
322                 LOGW("context: %p, source id: %d, source: %p", context, source_id, source);
323                 g_source_destroy(source);
324         }
325
326         MMPLAYER_FLEAVE();
327 }
328
329 gboolean
330 __mmplayer_dump_pipeline_state(mm_player_t* player)
331 {
332         GstIterator*iter = NULL;
333         gboolean done = FALSE;
334
335         GValue item = {0, };
336         GstElement *element = NULL;
337         GstElementFactory *factory = NULL;
338
339         GstState state = GST_STATE_VOID_PENDING;
340         GstState pending = GST_STATE_VOID_PENDING;
341         GstClockTime time = 200*GST_MSECOND;
342
343         MMPLAYER_FENTER();
344
345         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
346                 player->pipeline &&
347                 player->pipeline->mainbin,
348                 FALSE);
349
350         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
351
352         if (iter != NULL) {
353                 while (!done) {
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);
358
359                                 factory = gst_element_get_factory(element) ;
360                                 if (factory)
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);
364                                 break;
365                         case GST_ITERATOR_RESYNC:
366                                 gst_iterator_resync(iter);
367                                 break;
368                         case GST_ITERATOR_ERROR:
369                                 done = TRUE;
370                                 break;
371                         case GST_ITERATOR_DONE:
372                                 done = TRUE;
373                                 break;
374                         }
375                 }
376         }
377
378         element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
379
380         gst_element_get_state(element, &state, &pending, time);
381
382         factory = gst_element_get_factory(element) ;
383
384         if (factory) {
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));
391         }
392
393         g_value_unset(&item);
394
395         if (iter)
396                 gst_iterator_free(iter);
397
398         MMPLAYER_FLEAVE();
399
400         return FALSE;
401 }
402
403 const gchar *
404 __get_state_name(int state)
405 {
406         switch (state) {
407         case MM_PLAYER_STATE_NULL:
408                 return "NULL";
409         case MM_PLAYER_STATE_READY:
410                 return "READY";
411         case MM_PLAYER_STATE_PAUSED:
412                 return "PAUSED";
413         case MM_PLAYER_STATE_PLAYING:
414                 return "PLAYING";
415         case MM_PLAYER_STATE_NONE:
416                 return "NONE";
417         default:
418                 return "INVAID";
419         }
420 }
421
422 gboolean
423 __is_rtsp_streaming(mm_player_t* player)
424 {
425         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
426
427         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP) ? TRUE : FALSE;
428 }
429
430 gboolean
431 __is_wfd_streaming(mm_player_t* player)
432 {
433         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
434
435         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD) ? TRUE : FALSE;
436 }
437
438 gboolean
439 __is_http_streaming(mm_player_t* player)
440 {
441         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
442
443         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP) ? TRUE : FALSE;
444 }
445
446 gboolean
447 __is_streaming(mm_player_t* player)
448 {
449         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
450
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;
453 }
454
455 gboolean
456 __is_live_streaming(mm_player_t* player)
457 {
458         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
459
460         return (__is_rtsp_streaming(player) && player->streaming_type == STREAMING_SERVICE_LIVE) ? TRUE : FALSE;
461 }
462
463 gboolean
464 __is_http_live_streaming(mm_player_t* player)
465 {
466         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
467
468         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ? TRUE : FALSE;
469 }
470
471 gboolean
472 __is_dash_streaming(mm_player_t* player)
473 {
474         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
475
476         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH) ? TRUE : FALSE;
477 }
478
479 gboolean
480 __is_smooth_streaming(mm_player_t* player)
481 {
482         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
483
484         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) ? TRUE : FALSE;
485 }
486
487
488 gboolean
489 __is_http_progressive_down(mm_player_t* player)
490 {
491         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
492
493         return ((player->pd_mode) ? TRUE : FALSE);
494 }
495
496 /* if retval is FALSE, it will be dropped for perfomance. */
497 gboolean
498 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
499 {
500         gboolean retval = FALSE;
501
502         if (!(player->pipeline && player->pipeline->mainbin)) {
503                 LOGE("player pipeline handle is null");
504                 return TRUE;
505         }
506
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:
517                 retval = TRUE;
518                 break;
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))
523                         retval = TRUE;
524                 else
525                         retval = FALSE;
526                 break;
527         case GST_MESSAGE_BUFFERING:
528         {
529                 gint buffer_percent = 0;
530
531                 gst_message_parse_buffering(message, &buffer_percent);
532
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;
539                 }
540
541                 retval = TRUE;
542                 break;
543         }
544         default:
545                 retval = FALSE;
546                 break;
547         }
548
549         return retval;
550 }
551
552 gboolean
553 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param)
554 {
555         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
556
557         if (!player->msg_cb)
558                 return FALSE;
559
560         //LOGD("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
561
562         player->msg_cb(msgtype, param, player->msg_cb_param);
563
564         return TRUE;
565 }
566
567 gboolean
568 __mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* error)
569 {
570         MMMessageParamType msg_param;
571         gchar *msg_src_element;
572
573         MMPLAYER_FENTER();
574
575         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
576         MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
577
578         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
579
580         memset(&msg_param, 0, sizeof(MMMessageParamType));
581
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);
590         } else {
591                 LOGW("This error domain is not defined.\n");
592
593                 /* we treat system error as an internal error */
594                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
595         }
596
597         if (message->src) {
598                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
599
600                 msg_param.data = (void *) error->message;
601
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);
604         }
605
606         /* no error */
607         if (msg_param.code == MM_ERROR_NONE)
608                 return TRUE;
609
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;
615         } else
616                 LOGD("skip error post because it's sent already.\n");
617
618         MMPLAYER_FLEAVE();
619
620         return TRUE;
621 }
622
623 gint
624 __gst_handle_core_error(mm_player_t* player, int code)
625 {
626         gint trans_err = MM_ERROR_NONE;
627
628         MMPLAYER_FENTER();
629
630         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
631
632         switch (code) {
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:
648         default:
649                 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
650                 break;
651         }
652
653         MMPLAYER_FLEAVE();
654
655         return trans_err;
656 }
657
658 gint
659 __gst_handle_library_error(mm_player_t* player, int code)
660 {
661         gint trans_err = MM_ERROR_NONE;
662
663         MMPLAYER_FENTER();
664
665         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
666
667         switch (code) {
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:
674         default:
675                 trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
676                 break;
677         }
678
679         MMPLAYER_FLEAVE();
680
681         return trans_err;
682 }
683
684 gint
685 __gst_handle_resource_error(mm_player_t* player, int code)
686 {
687         gint trans_err = MM_ERROR_NONE;
688
689         MMPLAYER_FENTER();
690
691         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
692
693         switch (code) {
694         case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
695                 trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
696                 break;
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;
702                         break;
703                 }
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;
708                         break;
709                 }
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:
720         default:
721                 trans_err = MM_ERROR_PLAYER_INTERNAL;
722         break;
723         }
724
725         MMPLAYER_FLEAVE();
726
727         return trans_err;
728 }
729
730 gint
731 __gst_handle_stream_error(mm_player_t* player, GError* error, GstMessage * message)
732 {
733         gint trans_err = MM_ERROR_NONE;
734
735         MMPLAYER_FENTER();
736
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);
740
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);
750                 break;
751
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:
758         default:
759                 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
760                 break;
761         }
762
763         MMPLAYER_FLEAVE();
764
765         return trans_err;
766 }
767
768 /* NOTE : decide gstreamer state whether there is some playable track or not. */
769 static gint
770 __gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error)
771 {
772         gchar *src_element_name = NULL;
773         GstElement *src_element = NULL;
774         GstElementFactory *factory = NULL;
775         const gchar* klass = NULL;
776
777         MMPLAYER_FENTER();
778
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);
782
783         src_element = GST_ELEMENT_CAST(message->src);
784         if (!src_element)
785                 goto INTERNAL_ERROR;
786
787         src_element_name = GST_ELEMENT_NAME(src_element);
788         if (!src_element_name)
789                 goto INTERNAL_ERROR;
790
791         factory = gst_element_get_factory(src_element);
792         if (!factory)
793                 goto INTERNAL_ERROR;
794
795         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
796         if (!klass)
797                 goto INTERNAL_ERROR;
798
799         LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
800                         error->code, error->message, src_element_name, klass);
801
802         //<-
803         {
804                 if (player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst) {
805                         int msg_src_pos = 0;
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);
808
809                         if  (src_element_name) {
810                                 int idx = 0;
811
812                                 if (player->audio_decoders) {
813                                         GList *adec = player->audio_decoders;
814                                         for (; adec ; adec = g_list_next(adec)) {
815                                                 gchar *name = adec->data;
816
817                                                 LOGD("found audio decoder name  = %s", name);
818                                                 if (g_strrstr(name, src_element_name)) {
819                                                         msg_src_pos = idx;
820                                                         break;
821                                                 }
822                                                 idx++;
823                                         }
824                                 }
825                                 LOGD("active pad = %d, error src index = %d", active_pad_index,  msg_src_pos);
826                         }
827
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;
831                         }
832                 }
833         }
834         //-> check!! if needed or not
835
836         switch (error->code) {
837         case GST_STREAM_ERROR_DECODE:
838         {
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.
842                  */
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;
848                         } else {
849                                 if (player->pipeline->audiobin) // PCM
850                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
851                                 else
852                                         goto CODEC_NOT_FOUND;
853                         }
854                 }
855                 return MM_ERROR_PLAYER_INVALID_STREAM;
856         }
857                 break;
858
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;
863
864         case GST_STREAM_ERROR_FAILED:
865         {
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;
872                                 } else
873                                         goto CODEC_NOT_FOUND;
874
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;
879                                 } else
880                                         goto CODEC_NOT_FOUND;
881                         }
882                 }
883                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
884         }
885                 break;
886
887         case GST_STREAM_ERROR_DECRYPT:
888         case GST_STREAM_ERROR_DECRYPT_NOKEY:
889         {
890                 LOGE("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
891
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;
901         }
902                 break;
903
904         default:
905                 break;
906         }
907
908         MMPLAYER_FLEAVE();
909
910         return MM_ERROR_PLAYER_INVALID_STREAM;
911
912 INTERNAL_ERROR:
913         return MM_ERROR_PLAYER_INTERNAL;
914
915 CODEC_NOT_FOUND:
916         LOGD("not found any available codec. Player should be destroyed.\n");
917         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
918 }
919
920 int
921 __mmplayer_get_video_angle(mm_player_t* player, int *user_angle, int *org_angle)
922 {
923         int user_angle_type = 0;
924         gchar *org_orient = NULL;
925         MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
926
927         if (!attrs) {
928                 LOGE("cannot get content attribute");
929                 return MM_ERROR_PLAYER_INTERNAL;
930         }
931
932         /* update user roation */
933         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
934
935         /* get angle with user type */
936         switch (user_angle_type) {
937         case MM_DISPLAY_ROTATION_NONE:
938                 *user_angle = 0;
939                 break;
940         case MM_DISPLAY_ROTATION_90: /* counter-clockwise 90 */
941                 *user_angle = 270;
942                 break;
943         case MM_DISPLAY_ROTATION_180:
944                 *user_angle = 180;
945                 break;
946         case MM_DISPLAY_ROTATION_270: /* clockwise 90 */
947                 *user_angle = 90;
948                 break;
949         }
950
951         /* get original orientation */
952         mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
953
954         if (org_orient) {
955                 if (!strcmp(org_orient, "rotate-90"))
956                         *org_angle = 90;
957                 else if (!strcmp(org_orient, "rotate-180"))
958                         *org_angle = 180;
959                 else if (!strcmp(org_orient, "rotate-270"))
960                         *org_angle = 270;
961                 else
962                         LOGD("original rotation is %s", org_orient);
963         } else
964                 LOGD("content_video_orientation get fail");
965
966         LOGD("check user angle: %d, orientation: %d", *user_angle, *org_angle);
967
968         return MM_ERROR_NONE;
969 }
970