Merge "Support using wl_surface for legacy_player_test" into tizen
[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 #ifdef HAVE_WAYLAND
29 #include <gst/wayland/wayland.h>
30 #endif
31 #include <gst/video/videooverlay.h>
32
33 #include <dlog.h>
34 #include <mm_error.h>
35 #include <mm_attrs_private.h>
36
37 #include "mm_player_priv.h"
38 #include "mm_player_attrs.h"
39 #include "mm_player_utils.h"
40
41 /*===========================================================================================
42 |                                                                                                                                                                                       |
43 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
44 |                                                                                                                                                                                       |
45 ========================================================================================== */
46
47 /*---------------------------------------------------------------------------
48 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
49 ---------------------------------------------------------------------------*/
50
51 /*---------------------------------------------------------------------------
52 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
53 ---------------------------------------------------------------------------*/
54
55 /*---------------------------------------------------------------------------
56 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
57 ---------------------------------------------------------------------------*/
58
59 /*---------------------------------------------------------------------------
60 |    LOCAL #defines:                                                                                                            |
61 ---------------------------------------------------------------------------*/
62
63 /*---------------------------------------------------------------------------
64 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
65 ---------------------------------------------------------------------------*/
66
67 /*---------------------------------------------------------------------------
68 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
69 ---------------------------------------------------------------------------*/
70
71 /*---------------------------------------------------------------------------
72 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
73 ---------------------------------------------------------------------------*/
74
75 /*---------------------------------------------------------------------------
76 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
77 ---------------------------------------------------------------------------*/
78
79 /*---------------------------------------------------------------------------
80 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
81 ---------------------------------------------------------------------------*/
82 static gint __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
83
84 /*===========================================================================================
85 |                                                                                                                                                                                       |
86 |  FUNCTION DEFINITIONS                                                                                                                                         |
87 |                                                                                                                                                                                       |
88 ========================================================================================== */
89 int
90 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
91 {
92         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
93         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
94
95         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
96
97         //LOGD("incomming command : %d \n", command );
98
99         current_state = MMPLAYER_CURRENT_STATE(player);
100         pending_state = MMPLAYER_PENDING_STATE(player);
101
102         MMPLAYER_PRINT_STATE(player);
103
104         switch( command )
105         {
106                 case MMPLAYER_COMMAND_CREATE:
107                 {
108                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
109
110                         if ( current_state == MM_PLAYER_STATE_NULL ||
111                                 current_state == MM_PLAYER_STATE_READY ||
112                                 current_state == MM_PLAYER_STATE_PAUSED ||
113                                 current_state == MM_PLAYER_STATE_PLAYING )
114                                 goto NO_OP;
115                 }
116                 break;
117
118                 case MMPLAYER_COMMAND_DESTROY:
119                 {
120                         /* destroy can called anytime */
121
122                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
123                 }
124                 break;
125
126                 case MMPLAYER_COMMAND_REALIZE:
127                 {
128                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
129
130                         if ( pending_state != MM_PLAYER_STATE_NONE )
131                         {
132                                 goto INVALID_STATE;
133                         }
134                         else
135                         {
136                                 /* need ready state to realize */
137                                 if ( current_state == MM_PLAYER_STATE_READY )
138                                         goto NO_OP;
139
140                                 if ( current_state != MM_PLAYER_STATE_NULL )
141                                         goto INVALID_STATE;
142                         }
143                 }
144                 break;
145
146                 case MMPLAYER_COMMAND_UNREALIZE:
147                 {
148                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
149
150                         if ( current_state == MM_PLAYER_STATE_NULL )
151                                 goto NO_OP;
152                 }
153                 break;
154
155                 case MMPLAYER_COMMAND_START:
156                 {
157                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
158
159                         if ( pending_state == MM_PLAYER_STATE_NONE )
160                         {
161                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
162                                         goto NO_OP;
163                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
164                                         current_state != MM_PLAYER_STATE_PAUSED )
165                                         goto INVALID_STATE;
166                         }
167                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
168                         {
169                                 goto ALREADY_GOING;
170                         }
171                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
172                         {
173                                 LOGD("player is going to paused state, just change the pending state as playing");
174                         }
175                         else
176                         {
177                                 goto INVALID_STATE;
178                         }
179                 }
180                 break;
181
182                 case MMPLAYER_COMMAND_STOP:
183                 {
184                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
185
186                         if ( current_state == MM_PLAYER_STATE_READY )
187                                 goto NO_OP;
188
189                         /* need playing/paused state to stop */
190                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
191                                  current_state != MM_PLAYER_STATE_PAUSED )
192                                 goto INVALID_STATE;
193                 }
194                 break;
195
196                 case MMPLAYER_COMMAND_PAUSE:
197                 {
198                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
199                                 goto NO_OP;
200
201                         if (player->doing_seek)
202                                 goto NOT_COMPLETED_SEEK;
203
204                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
205
206                         if ( pending_state == MM_PLAYER_STATE_NONE )
207                         {
208                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
209                                         goto NO_OP;
210                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
211                                         goto INVALID_STATE;
212                         }
213                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
214                         {
215                                 goto ALREADY_GOING;
216                         }
217                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
218                         {
219                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
220                                         LOGD("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
221                                 } else {
222                                         goto INVALID_STATE;
223                                 }
224                         }
225                 }
226                 break;
227
228                 case MMPLAYER_COMMAND_RESUME:
229                 {
230
231                         if (player->doing_seek)
232                                 goto NOT_COMPLETED_SEEK;
233
234                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
235
236                         if ( pending_state == MM_PLAYER_STATE_NONE )
237                         {
238                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
239                                         goto NO_OP;
240                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
241                                         goto INVALID_STATE;
242                         }
243                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
244                         {
245                                 goto ALREADY_GOING;
246                         }
247                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
248                         {
249                                 LOGD("player is going to paused state, just change the pending state as playing");
250                         }
251                         else
252                         {
253                                 goto INVALID_STATE;
254                         }
255                 }
256                 break;
257
258                 default:
259                 break;
260         }
261         player->cmd = command;
262
263         return MM_ERROR_NONE;
264
265 INVALID_STATE:
266         LOGW("since player is in wrong state(%s). it's not able to apply the command(%d)",
267                 MMPLAYER_STATE_GET_NAME(current_state), command);
268         return MM_ERROR_PLAYER_INVALID_STATE;
269
270 NOT_COMPLETED_SEEK:
271         LOGW("not completed seek");
272         return MM_ERROR_PLAYER_DOING_SEEK;
273
274 NO_OP:
275         LOGW("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
276         return MM_ERROR_PLAYER_NO_OP;
277
278 ALREADY_GOING:
279         LOGW("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
280         return MM_ERROR_PLAYER_NO_OP;
281 }
282
283 int
284 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout)
285 {
286         GstState element_state = GST_STATE_VOID_PENDING;
287         GstState element_pending_state = GST_STATE_VOID_PENDING;
288         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
289
290         MMPLAYER_FENTER();
291
292         MMPLAYER_RETURN_VAL_IF_FAIL ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
293         MMPLAYER_RETURN_VAL_IF_FAIL ( element, MM_ERROR_INVALID_ARGUMENT );
294
295         LOGD("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
296
297         /* set state */
298         ret = gst_element_set_state(element, state);
299
300         if ( ret == GST_STATE_CHANGE_FAILURE )
301         {
302                 LOGE("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
303
304                 /* dump state of all element */
305                 __mmplayer_dump_pipeline_state( player );
306
307                 return MM_ERROR_PLAYER_INTERNAL;
308         }
309
310         /* return here so state transition to be done in async mode */
311         if ( async )
312         {
313                 LOGD("async state transition. not waiting for state complete.\n");
314                 return MM_ERROR_NONE;
315         }
316
317         /* wait for state transition */
318         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
319
320         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
321         {
322                 LOGE("failed to change [%s] element state to [%s] within %d sec\n",
323                         GST_ELEMENT_NAME(element),
324                         gst_element_state_get_name(state), timeout );
325
326                 LOGE(" [%s] state : %s   pending : %s \n",
327                         GST_ELEMENT_NAME(element),
328                         gst_element_state_get_name(element_state),
329                         gst_element_state_get_name(element_pending_state) );
330
331                 /* dump state of all element */
332                 __mmplayer_dump_pipeline_state( player );
333
334                 return MM_ERROR_PLAYER_INTERNAL;
335         }
336
337         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
338
339         MMPLAYER_FLEAVE();
340
341         return MM_ERROR_NONE;
342 }
343
344 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
345 {
346         GSource *source = NULL;
347
348         MMPLAYER_FENTER();
349
350         source = g_main_context_find_source_by_id (context, source_id);
351
352         if (source != NULL)
353         {
354                 LOGW("context: %p, source id: %d, source: %p", context, source_id, source);
355                 g_source_destroy(source);
356         }
357
358         MMPLAYER_FLEAVE();
359 }
360
361 gboolean
362 __mmplayer_dump_pipeline_state( mm_player_t* player )
363 {
364         GstIterator*iter = NULL;
365         gboolean done = FALSE;
366
367         GValue item = {0, };
368         GstElement *element = NULL;
369         GstElementFactory *factory = NULL;
370
371         GstState state = GST_STATE_VOID_PENDING;
372         GstState pending = GST_STATE_VOID_PENDING;
373         GstClockTime time = 200*GST_MSECOND;
374
375         MMPLAYER_FENTER();
376
377         MMPLAYER_RETURN_VAL_IF_FAIL ( player &&
378                 player->pipeline &&
379                 player->pipeline->mainbin,
380                 FALSE );
381
382         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
383
384         if ( iter != NULL )
385         {
386                 while (!done) {
387                          switch ( gst_iterator_next (iter, &item) )
388                          {
389                            case GST_ITERATOR_OK:
390                                 element = g_value_get_object(&item);
391                                 gst_element_get_state(element,&state, &pending,time);
392
393                                 factory = gst_element_get_factory (element) ;
394                                 if (factory)
395                                 {
396                                         LOGE("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
397                                                 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
398                                 }
399                                  g_value_reset (&item);
400                                  break;
401                            case GST_ITERATOR_RESYNC:
402                                  gst_iterator_resync (iter);
403                                  break;
404                            case GST_ITERATOR_ERROR:
405                                  done = TRUE;
406                                  break;
407                            case GST_ITERATOR_DONE:
408                                  done = TRUE;
409                                  break;
410                          }
411                 }
412         }
413
414         element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
415
416         gst_element_get_state(element,&state, &pending,time);
417
418         factory = gst_element_get_factory (element) ;
419
420         if (factory)
421         {
422                 LOGE("%s:%s : From:%s To:%s  refcount : %d\n",
423                         GST_OBJECT_NAME(factory),
424                         GST_ELEMENT_NAME(element),
425                         gst_element_state_get_name(state),
426                         gst_element_state_get_name(pending),
427                         GST_OBJECT_REFCOUNT_VALUE(element) );
428         }
429
430         g_value_unset(&item);
431
432         if ( iter )
433                 gst_iterator_free (iter);
434
435         MMPLAYER_FLEAVE();
436
437         return FALSE;
438 }
439
440 const gchar *
441 __get_state_name ( int state )
442 {
443         switch ( state )
444         {
445                 case MM_PLAYER_STATE_NULL:
446                         return "NULL";
447                 case MM_PLAYER_STATE_READY:
448                         return "READY";
449                 case MM_PLAYER_STATE_PAUSED:
450                         return "PAUSED";
451                 case MM_PLAYER_STATE_PLAYING:
452                         return "PLAYING";
453                 case MM_PLAYER_STATE_NONE:
454                         return "NONE";
455                 default:
456                         return "INVAID";
457         }
458 }
459
460 gboolean
461 __is_rtsp_streaming ( mm_player_t* player )
462 {
463         MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
464
465         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
466 }
467
468 gboolean
469 __is_wfd_streaming ( mm_player_t* player )
470 {
471   MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
472
473   return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
474 }
475
476 gboolean
477 __is_http_streaming ( mm_player_t* player )
478 {
479         MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
480
481         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
482 }
483
484 gboolean
485 __is_streaming ( mm_player_t* player )
486 {
487         MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
488
489   return ( __is_http_progressive_down( player ) || __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
490           || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
491 }
492
493 gboolean
494 __is_live_streaming ( mm_player_t* player )
495 {
496         MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
497
498         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
499 }
500
501 gboolean
502 __is_http_live_streaming( mm_player_t* player )
503 {
504         MMPLAYER_RETURN_VAL_IF_FAIL( player, FALSE );
505
506         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
507 }
508
509 gboolean
510 __is_dash_streaming ( mm_player_t* player )
511 {
512         MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
513
514         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
515 }
516
517 gboolean
518 __is_smooth_streaming ( mm_player_t* player )
519 {
520         MMPLAYER_RETURN_VAL_IF_FAIL ( player, FALSE );
521
522         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
523 }
524
525
526 gboolean
527 __is_http_progressive_down(mm_player_t* player)
528 {
529         MMPLAYER_RETURN_VAL_IF_FAIL( player, FALSE );
530
531         return ((player->pd_mode) ? TRUE:FALSE);
532 }
533
534 /* if retval is FALSE, it will be dropped for perfomance. */
535 gboolean
536 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
537 {
538         gboolean retval = FALSE;
539
540         if ( !(player->pipeline && player->pipeline->mainbin) )
541         {
542                 LOGE("player pipeline handle is null");
543                 return TRUE;
544         }
545
546         switch (GST_MESSAGE_TYPE (message))
547         {
548                 case GST_MESSAGE_TAG:
549                 case GST_MESSAGE_EOS:
550                 case GST_MESSAGE_ERROR:
551                 case GST_MESSAGE_WARNING:
552                 case GST_MESSAGE_CLOCK_LOST:
553                 case GST_MESSAGE_NEW_CLOCK:
554                 case GST_MESSAGE_ELEMENT:
555                 case GST_MESSAGE_DURATION_CHANGED:
556                 case GST_MESSAGE_ASYNC_START:
557                         retval = TRUE;
558                         break;
559                 case GST_MESSAGE_ASYNC_DONE:
560                 case GST_MESSAGE_STATE_CHANGED:
561                         /* we only handle messages from pipeline */
562                         if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->gapless.reconfigure))
563                                 retval = TRUE;
564                         else
565                                 retval = FALSE;
566                         break;
567                 case GST_MESSAGE_BUFFERING:
568                 {
569                         gint buffer_percent = 0;
570
571                         gst_message_parse_buffering (message, &buffer_percent);
572
573                         if ((MMPLAYER_IS_STREAMING(player)) &&
574                                 (player->streamer) &&
575                                 (player->streamer->is_buffering == TRUE) &&
576                                 (buffer_percent == MAX_BUFFER_PERCENT))
577                         {
578                                 LOGD (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
579                                 player->streamer->is_buffering_done = TRUE;
580                         }
581
582                         retval = TRUE;
583                         break;
584                 }
585                 default:
586                         retval = FALSE;
587                         break;
588         }
589
590         return retval;
591 }
592
593 gboolean
594 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param)
595 {
596         MMPLAYER_RETURN_VAL_IF_FAIL( player, FALSE );
597
598         if ( !player->msg_cb )
599         {
600                 return FALSE;
601         }
602
603         //LOGD("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
604
605         player->msg_cb(msgtype, param, player->msg_cb_param);
606
607         return TRUE;
608 }
609
610 gboolean
611 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
612 {
613         MMMessageParamType msg_param;
614         gchar *msg_src_element;
615
616         MMPLAYER_FENTER();
617
618         MMPLAYER_RETURN_VAL_IF_FAIL( player, FALSE );
619         MMPLAYER_RETURN_VAL_IF_FAIL( error, FALSE );
620
621         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
622
623         memset (&msg_param, 0, sizeof(MMMessageParamType));
624
625         if ( error->domain == GST_CORE_ERROR )
626         {
627                 msg_param.code = __gst_handle_core_error( player, error->code );
628         }
629         else if ( error->domain == GST_LIBRARY_ERROR )
630         {
631                 msg_param.code = __gst_handle_library_error( player, error->code );
632         }
633         else if ( error->domain == GST_RESOURCE_ERROR )
634         {
635                 msg_param.code = __gst_handle_resource_error( player, error->code );
636         }
637         else if ( error->domain == GST_STREAM_ERROR )
638         {
639                 msg_param.code = __gst_handle_stream_error( player, error, message );
640         }
641         else
642         {
643                 LOGW("This error domain is not defined.\n");
644
645                 /* we treat system error as an internal error */
646                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
647         }
648
649         if ( message->src )
650         {
651                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
652
653                 msg_param.data = (void *) error->message;
654
655                 LOGE("-Msg src : [%s]   Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
656                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
657         }
658
659         /* no error */
660         if (msg_param.code == MM_ERROR_NONE)
661                 return TRUE;
662
663         /* post error to application */
664         if ( ! player->msg_posted )
665         {
666                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
667                 /* don't post more if one was sent already */
668                 player->msg_posted = TRUE;
669         }
670         else
671         {
672                 LOGD("skip error post because it's sent already.\n");
673         }
674
675         MMPLAYER_FLEAVE();
676
677         return TRUE;
678 }
679
680 gint
681 __gst_handle_core_error( mm_player_t* player, int code )
682 {
683         gint trans_err = MM_ERROR_NONE;
684
685         MMPLAYER_FENTER();
686
687         MMPLAYER_RETURN_VAL_IF_FAIL( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
688
689         switch ( code )
690         {
691                 case GST_CORE_ERROR_MISSING_PLUGIN:
692                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
693                 case GST_CORE_ERROR_STATE_CHANGE:
694                 case GST_CORE_ERROR_SEEK:
695                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
696                 case GST_CORE_ERROR_FAILED:
697                 case GST_CORE_ERROR_TOO_LAZY:
698                 case GST_CORE_ERROR_PAD:
699                 case GST_CORE_ERROR_THREAD:
700                 case GST_CORE_ERROR_NEGOTIATION:
701                 case GST_CORE_ERROR_EVENT:
702                 case GST_CORE_ERROR_CAPS:
703                 case GST_CORE_ERROR_TAG:
704                 case GST_CORE_ERROR_CLOCK:
705                 case GST_CORE_ERROR_DISABLED:
706                 default:
707                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
708                 break;
709         }
710
711         MMPLAYER_FLEAVE();
712
713         return trans_err;
714 }
715
716 gint
717 __gst_handle_library_error( mm_player_t* player, int code )
718 {
719         gint trans_err = MM_ERROR_NONE;
720
721         MMPLAYER_FENTER();
722
723         MMPLAYER_RETURN_VAL_IF_FAIL( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
724
725         switch ( code )
726         {
727                 case GST_LIBRARY_ERROR_FAILED:
728                 case GST_LIBRARY_ERROR_TOO_LAZY:
729                 case GST_LIBRARY_ERROR_INIT:
730                 case GST_LIBRARY_ERROR_SHUTDOWN:
731                 case GST_LIBRARY_ERROR_SETTINGS:
732                 case GST_LIBRARY_ERROR_ENCODE:
733                 default:
734                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
735                 break;
736         }
737
738         MMPLAYER_FLEAVE();
739
740         return trans_err;
741 }
742
743 gint
744 __gst_handle_resource_error( mm_player_t* player, int code )
745 {
746         gint trans_err = MM_ERROR_NONE;
747
748         MMPLAYER_FENTER();
749
750         MMPLAYER_RETURN_VAL_IF_FAIL( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
751
752         switch ( code )
753         {
754                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
755                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
756                         break;
757                 case GST_RESOURCE_ERROR_NOT_FOUND:
758                 case GST_RESOURCE_ERROR_OPEN_READ:
759                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
760                                 || MMPLAYER_IS_RTSP_STREAMING(player))
761                         {
762                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
763                                 break;
764                         }
765                 case GST_RESOURCE_ERROR_READ:
766                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
767                                 || MMPLAYER_IS_RTSP_STREAMING(player))
768                         {
769                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
770                                 break;
771                         }
772                 case GST_RESOURCE_ERROR_WRITE:
773                 case GST_RESOURCE_ERROR_FAILED:
774                 case GST_RESOURCE_ERROR_SEEK:
775                 case GST_RESOURCE_ERROR_TOO_LAZY:
776                 case GST_RESOURCE_ERROR_BUSY:
777                 case GST_RESOURCE_ERROR_OPEN_WRITE:
778                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
779                 case GST_RESOURCE_ERROR_CLOSE:
780                 case GST_RESOURCE_ERROR_SYNC:
781                 case GST_RESOURCE_ERROR_SETTINGS:
782                 default:
783                         trans_err = MM_ERROR_PLAYER_INTERNAL;
784                 break;
785         }
786
787         MMPLAYER_FLEAVE();
788
789         return trans_err;
790 }
791
792 gint
793 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
794 {
795         gint trans_err = MM_ERROR_NONE;
796
797         MMPLAYER_FENTER();
798
799         MMPLAYER_RETURN_VAL_IF_FAIL( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
800         MMPLAYER_RETURN_VAL_IF_FAIL( error, MM_ERROR_INVALID_ARGUMENT );
801         MMPLAYER_RETURN_VAL_IF_FAIL ( message, MM_ERROR_INVALID_ARGUMENT );
802
803         switch ( error->code )
804         {
805                 case GST_STREAM_ERROR_FAILED:
806                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
807                 case GST_STREAM_ERROR_DECODE:
808                 case GST_STREAM_ERROR_WRONG_TYPE:
809                 case GST_STREAM_ERROR_DECRYPT:
810                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
811                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
812                          trans_err = __gst_transform_gsterror( player, message, error );
813                 break;
814
815                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
816                 case GST_STREAM_ERROR_TOO_LAZY:
817                 case GST_STREAM_ERROR_ENCODE:
818                 case GST_STREAM_ERROR_DEMUX:
819                 case GST_STREAM_ERROR_MUX:
820                 case GST_STREAM_ERROR_FORMAT:
821                 default:
822                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
823                 break;
824         }
825
826         MMPLAYER_FLEAVE();
827
828         return trans_err;
829 }
830
831 /* NOTE : decide gstreamer state whether there is some playable track or not. */
832 static gint
833 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
834 {
835         gchar *src_element_name = NULL;
836         GstElement *src_element = NULL;
837         GstElementFactory *factory = NULL;
838         const gchar* klass = NULL;
839
840         MMPLAYER_FENTER();
841
842         MMPLAYER_RETURN_VAL_IF_FAIL ( message, MM_ERROR_INVALID_ARGUMENT );
843         MMPLAYER_RETURN_VAL_IF_FAIL ( message->src, MM_ERROR_INVALID_ARGUMENT );
844         MMPLAYER_RETURN_VAL_IF_FAIL ( error, MM_ERROR_INVALID_ARGUMENT );
845
846         src_element = GST_ELEMENT_CAST(message->src);
847         if ( !src_element )
848                 goto INTERNAL_ERROR;
849
850         src_element_name = GST_ELEMENT_NAME(src_element);
851         if ( !src_element_name )
852                 goto INTERNAL_ERROR;
853
854         factory = gst_element_get_factory(src_element);
855         if ( !factory )
856                 goto INTERNAL_ERROR;
857
858         klass = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
859         if ( !klass )
860                 goto INTERNAL_ERROR;
861
862         LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
863                         error->code, error->message, src_element_name, klass);
864
865         //<-
866         {
867                 if (player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst) {
868                         int msg_src_pos = 0;
869                         gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
870                         LOGD ("current  active pad index  -%d", active_pad_index);
871
872                         if  (src_element_name) {
873                                 int idx = 0;
874
875                                 if (player->audio_decoders) {
876                                         GList *adec = player->audio_decoders;
877                                         for ( ;adec ; adec = g_list_next(adec)) {
878                                                 gchar *name = adec->data;
879
880                                                 LOGD("found audio decoder name  = %s", name);
881                                                 if (g_strrstr(name, src_element_name)) {
882                                                         msg_src_pos = idx;
883                                                         break;
884                                                 }
885                                                 idx++;
886                                         }
887                                 }
888                                 LOGD("active pad = %d, error src index = %d", active_pad_index,  msg_src_pos);
889                         }
890
891                         if (active_pad_index != msg_src_pos) {
892                                 LOGD("skip error because error is posted from no activated track");
893                                 return MM_ERROR_NONE;
894                         }
895                 }
896         }
897         //-> check!! if needed or not
898
899         switch ( error->code )
900         {
901                 case GST_STREAM_ERROR_DECODE:
902                 {
903                         /* Demuxer can't parse one track because it's corrupted.
904                          * So, the decoder for it is not linked.
905                          * But, it has one playable track.
906                          */
907                         if ( g_strrstr(klass, "Demux") )
908                         {
909                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
910                                 {
911                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
912                                 }
913                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
914                                 {
915                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
916                                 }
917                                 else
918                                 {
919                                         if ( player->pipeline->audiobin ) // PCM
920                                         {
921                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
922                                         }
923                                         else
924                                         {
925                                                 goto CODEC_NOT_FOUND;
926                                         }
927                                 }
928                         }
929                         return MM_ERROR_PLAYER_INVALID_STREAM;
930                 }
931                 break;
932
933                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
934                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
935                 case GST_STREAM_ERROR_WRONG_TYPE:
936                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
937
938                 case GST_STREAM_ERROR_FAILED:
939                 {
940                         /* Decoder Custom Message */
941                         if ( strstr(error->message, "ongoing") )
942                         {
943                                 if ( strncasecmp(klass, "audio", 5) )
944                                 {
945                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
946                                         {
947                                                 LOGD("Video can keep playing.\n");
948                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
949                                         }
950                                         else
951                                         {
952                                                 goto CODEC_NOT_FOUND;
953                                         }
954
955                                 }
956                                 else if ( strncasecmp(klass, "video", 5) )
957                                 {
958                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
959                                         {
960                                                 LOGD("Audio can keep playing.\n");
961                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
962                                         }
963                                         else
964                                         {
965                                                 goto CODEC_NOT_FOUND;
966                                         }
967                                 }
968                         }
969                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
970                 }
971                 break;
972
973                 case GST_STREAM_ERROR_DECRYPT:
974                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
975                 {
976                         LOGE("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
977
978                         if ( strstr(error->message, "rights expired") )
979                         {
980                                 return MM_ERROR_PLAYER_DRM_EXPIRED;
981                         }
982                         else if ( strstr(error->message, "no rights") )
983                         {
984                                 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
985                         }
986                         else if ( strstr(error->message, "has future rights") )
987                         {
988                                 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
989                         }
990                         else if ( strstr(error->message, "opl violation") )
991                         {
992                                 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
993                         }
994                         return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
995                 }
996                 break;
997
998                 default:
999                 break;
1000         }
1001
1002         MMPLAYER_FLEAVE();
1003
1004         return MM_ERROR_PLAYER_INVALID_STREAM;
1005
1006 INTERNAL_ERROR:
1007         return MM_ERROR_PLAYER_INTERNAL;
1008
1009 CODEC_NOT_FOUND:
1010         LOGD("not found any available codec. Player should be destroyed.\n");
1011         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
1012 }
1013
1014 int
1015 __mmplayer_get_video_angle(mm_player_t* player, int *user_angle, int *org_angle)
1016 {
1017         int user_angle_type= 0;
1018         gchar *org_orient = NULL;
1019         MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
1020
1021         if ( !attrs )
1022         {
1023                 LOGE("cannot get content attribute");
1024                 return MM_ERROR_PLAYER_INTERNAL;
1025         }
1026
1027         /* update user roation */
1028         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
1029
1030         /* get angle with user type */
1031         switch(user_angle_type)
1032         {
1033                 case MM_DISPLAY_ROTATION_NONE:
1034                         *user_angle = 0;
1035                         break;
1036                 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
1037                         *user_angle = 270;
1038                         break;
1039                 case MM_DISPLAY_ROTATION_180:
1040                         *user_angle = 180;
1041                         break;
1042                 case MM_DISPLAY_ROTATION_270: // clockwise 90
1043                         *user_angle = 90;
1044                         break;
1045         }
1046
1047         /* get original orientation */
1048         mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
1049
1050         if (org_orient)
1051         {
1052                 if (!strcmp (org_orient, "rotate-90"))
1053                         *org_angle = 90;
1054                 else if (!strcmp (org_orient, "rotate-180"))
1055                         *org_angle = 180;
1056                 else if (!strcmp (org_orient, "rotate-270"))
1057                         *org_angle = 270;
1058                 else
1059                         LOGD ("original rotation is %s", org_orient);
1060         }
1061         else
1062         {
1063                 LOGD ("content_video_orientation get fail");
1064         }
1065
1066         LOGD("check user angle: %d, orientation: %d", *user_angle, *org_angle);
1067
1068         return MM_ERROR_NONE;
1069 }
1070