Merge "es_playback: add buffer status signal connection in push mode" 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 #include <glib.h>
29 #include <gst/gst.h>
30 #include <gst/app/gstappsrc.h>
31 #include <gst/video/videooverlay.h>
32 #ifdef HAVE_WAYLAND
33 #include <gst/wayland/wayland.h>
34 #endif
35 #include <unistd.h>
36 #include <sys/stat.h>
37 #include <string.h>
38 #include <sys/time.h>
39 #include <stdlib.h>
40
41 #include <mm_error.h>
42 #include <mm_attrs.h>
43 #include <mm_attrs_private.h>
44 #include <mm_debug.h>
45
46 #include "mm_player_priv.h"
47 #include "mm_player_ini.h"
48 #include "mm_player_attrs.h"
49 #include "mm_player_utils.h"
50 #include <sched.h>
51
52 /*===========================================================================================
53 |                                                                                                                                                                                       |
54 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
55 |                                                                                                                                                                                       |
56 ========================================================================================== */
57
58 /*---------------------------------------------------------------------------
59 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
60 ---------------------------------------------------------------------------*/
61
62 /*---------------------------------------------------------------------------
63 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
64 ---------------------------------------------------------------------------*/
65
66 /*---------------------------------------------------------------------------
67 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
68 ---------------------------------------------------------------------------*/
69
70 /*---------------------------------------------------------------------------
71 |    LOCAL #defines:                                                                                                            |
72 ---------------------------------------------------------------------------*/
73
74 /*---------------------------------------------------------------------------
75 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
76 ---------------------------------------------------------------------------*/
77
78 /*---------------------------------------------------------------------------
79 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
80 ---------------------------------------------------------------------------*/
81
82 /*---------------------------------------------------------------------------
83 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
84 ---------------------------------------------------------------------------*/
85
86 /*---------------------------------------------------------------------------
87 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
88 ---------------------------------------------------------------------------*/
89
90 /*---------------------------------------------------------------------------
91 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
92 ---------------------------------------------------------------------------*/
93 static gint __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
94
95 /*===========================================================================================
96 |                                                                                                                                                                                       |
97 |  FUNCTION DEFINITIONS                                                                                                                                         |
98 |                                                                                                                                                                                       |
99 ========================================================================================== */
100 int
101 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
102 {
103         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
104         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
105 //      MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
106 //      MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
107
108         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
109
110         //debug_log("incomming command : %d \n", command );
111
112         current_state = MMPLAYER_CURRENT_STATE(player);
113         pending_state = MMPLAYER_PENDING_STATE(player);
114 //      target_state = MMPLAYER_TARGET_STATE(player);
115 //      prev_state = MMPLAYER_PREV_STATE(player);
116
117         MMPLAYER_PRINT_STATE(player);
118
119         switch( command )
120         {
121                 case MMPLAYER_COMMAND_CREATE:
122                 {
123                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
124
125                         if ( current_state == MM_PLAYER_STATE_NULL ||
126                                 current_state == MM_PLAYER_STATE_READY ||
127                                 current_state == MM_PLAYER_STATE_PAUSED ||
128                                 current_state == MM_PLAYER_STATE_PLAYING )
129                                 goto NO_OP;
130                 }
131                 break;
132
133                 case MMPLAYER_COMMAND_DESTROY:
134                 {
135                         /* destroy can called anytime */
136
137                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
138                 }
139                 break;
140
141                 case MMPLAYER_COMMAND_REALIZE:
142                 {
143                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
144
145                         if ( pending_state != MM_PLAYER_STATE_NONE )
146                         {
147                                 goto INVALID_STATE;
148                         }
149                         else
150                         {
151                                 /* need ready state to realize */
152                                 if ( current_state == MM_PLAYER_STATE_READY )
153                                         goto NO_OP;
154
155                                 if ( current_state != MM_PLAYER_STATE_NULL )
156                                         goto INVALID_STATE;
157                         }
158                 }
159                 break;
160
161                 case MMPLAYER_COMMAND_UNREALIZE:
162                 {
163                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
164
165                         if ( current_state == MM_PLAYER_STATE_NULL )
166                                 goto NO_OP;
167                 }
168                 break;
169
170                 case MMPLAYER_COMMAND_START:
171                 {
172                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
173
174                         if ( pending_state == MM_PLAYER_STATE_NONE )
175                         {
176                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
177                                         goto NO_OP;
178                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
179                                         current_state != MM_PLAYER_STATE_PAUSED )
180                                         goto INVALID_STATE;
181                         }
182                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
183                         {
184                                 goto ALREADY_GOING;
185                         }
186                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
187                         {
188                                 debug_log("player is going to paused state, just change the pending state as playing");
189                         }
190                         else
191                         {
192                                 goto INVALID_STATE;
193                         }
194                 }
195                 break;
196
197                 case MMPLAYER_COMMAND_STOP:
198                 {
199                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
200
201                         if ( current_state == MM_PLAYER_STATE_READY )
202                                 goto NO_OP;
203
204                         /* need playing/paused state to stop */
205                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
206                                  current_state != MM_PLAYER_STATE_PAUSED )
207                                 goto INVALID_STATE;
208                 }
209                 break;
210
211                 case MMPLAYER_COMMAND_PAUSE:
212                 {
213                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
214                                 goto NO_OP;
215
216                         if (player->doing_seek)
217                                 goto NOT_COMPLETED_SEEK;
218
219                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
220
221                         if ( pending_state == MM_PLAYER_STATE_NONE )
222                         {
223                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
224                                         goto NO_OP;
225                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
226                                         goto INVALID_STATE;
227                         }
228                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
229                         {
230                                 goto ALREADY_GOING;
231                         }
232                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
233                         {
234                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
235                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
236                                 } else {
237                                         goto INVALID_STATE;
238                                 }
239                         }
240                 }
241                 break;
242
243                 case MMPLAYER_COMMAND_RESUME:
244                 {
245
246                         if (player->doing_seek)
247                                 goto NOT_COMPLETED_SEEK;
248
249                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
250
251                         if ( pending_state == MM_PLAYER_STATE_NONE )
252                         {
253                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
254                                         goto NO_OP;
255                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
256                                         goto INVALID_STATE;
257                         }
258                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
259                         {
260                                 goto ALREADY_GOING;
261                         }
262                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
263                         {
264                                 debug_log("player is going to paused state, just change the pending state as playing");
265                         }
266                         else
267                         {
268                                 goto INVALID_STATE;
269                         }
270                 }
271                 break;
272
273                 default:
274                 break;
275         }
276         player->cmd = command;
277
278         return MM_ERROR_NONE;
279
280 INVALID_STATE:
281         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
282                 MMPLAYER_STATE_GET_NAME(current_state), command);
283         return MM_ERROR_PLAYER_INVALID_STATE;
284
285 NOT_COMPLETED_SEEK:
286         debug_warning("not completed seek");
287         return MM_ERROR_PLAYER_DOING_SEEK;
288
289 NO_OP:
290         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
291         return MM_ERROR_PLAYER_NO_OP;
292
293 ALREADY_GOING:
294         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
295         return MM_ERROR_PLAYER_NO_OP;
296 }
297
298 int
299 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout) // @
300 {
301         GstState element_state = GST_STATE_VOID_PENDING;
302         GstState element_pending_state = GST_STATE_VOID_PENDING;
303         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
304
305         MMPLAYER_FENTER();
306
307         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
308         return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
309
310         debug_log("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
311
312         /* set state */
313         ret = gst_element_set_state(element, state);
314
315         if ( ret == GST_STATE_CHANGE_FAILURE )
316         {
317                 debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
318
319                 /* dump state of all element */
320                 __mmplayer_dump_pipeline_state( player );
321
322                 return MM_ERROR_PLAYER_INTERNAL;
323         }
324
325         /* return here so state transition to be done in async mode */
326         if ( async )
327         {
328                 debug_log("async state transition. not waiting for state complete.\n");
329                 return MM_ERROR_NONE;
330         }
331
332         /* wait for state transition */
333         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
334
335         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
336         {
337                 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
338                         GST_ELEMENT_NAME(element),
339                         gst_element_state_get_name(state), timeout );
340
341                 debug_error(" [%s] state : %s   pending : %s \n",
342                         GST_ELEMENT_NAME(element),
343                         gst_element_state_get_name(element_state),
344                         gst_element_state_get_name(element_pending_state) );
345
346                 /* dump state of all element */
347                 __mmplayer_dump_pipeline_state( player );
348
349                 return MM_ERROR_PLAYER_INTERNAL;
350         }
351
352         debug_log("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
353
354         MMPLAYER_FLEAVE();
355
356         return MM_ERROR_NONE;
357 }
358
359 void __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
360 {
361         GSource *source = NULL;
362
363         MMPLAYER_FENTER();
364
365         source = g_main_context_find_source_by_id (context, source_id);
366
367         if (source != NULL)
368         {
369                 debug_warning("context: %p, source id: %d, source: %p", context, source_id, source);
370                 g_source_destroy(source);
371         }
372
373         MMPLAYER_FLEAVE();
374 }
375
376 gboolean
377 __mmplayer_dump_pipeline_state( mm_player_t* player )
378 {
379         GstIterator*iter = NULL;
380         gboolean done = FALSE;
381
382         GValue item = {0, };
383         GstElement *element = NULL;
384         GstElementFactory *factory = NULL;
385
386         GstState state = GST_STATE_VOID_PENDING;
387         GstState pending = GST_STATE_VOID_PENDING;
388         GstClockTime time = 200*GST_MSECOND;
389
390         MMPLAYER_FENTER();
391
392         return_val_if_fail ( player &&
393                 player->pipeline &&
394                 player->pipeline->mainbin,
395                 FALSE );
396
397         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
398
399         if ( iter != NULL )
400         {
401                 while (!done) {
402                          switch ( gst_iterator_next (iter, &item) )
403                          {
404                            case GST_ITERATOR_OK:
405                                 element = g_value_get_object(&item);
406                                 gst_element_get_state(element,&state, &pending,time);
407
408                                 factory = gst_element_get_factory (element) ;
409                                 if (factory)
410                                 {
411                                         debug_error("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
412                                                 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
413                                 }
414                                  g_value_reset (&item);
415                                  break;
416                            case GST_ITERATOR_RESYNC:
417                                  gst_iterator_resync (iter);
418                                  break;
419                            case GST_ITERATOR_ERROR:
420                                  done = TRUE;
421                                  break;
422                            case GST_ITERATOR_DONE:
423                                  done = TRUE;
424                                  break;
425                          }
426                 }
427         }
428
429         element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
430
431         gst_element_get_state(element,&state, &pending,time);
432
433         factory = gst_element_get_factory (element) ;
434
435         if (factory)
436         {
437                 debug_error("%s:%s : From:%s To:%s  refcount : %d\n",
438                         GST_OBJECT_NAME(factory),
439                         GST_ELEMENT_NAME(element),
440                         gst_element_state_get_name(state),
441                         gst_element_state_get_name(pending),
442                         GST_OBJECT_REFCOUNT_VALUE(element) );
443         }
444
445         g_value_unset(&item);
446
447         if ( iter )
448                 gst_iterator_free (iter);
449
450         MMPLAYER_FLEAVE();
451
452         return FALSE;
453 }
454
455 const gchar *
456 __get_state_name ( int state )
457 {
458         switch ( state )
459         {
460                 case MM_PLAYER_STATE_NULL:
461                         return "NULL";
462                 case MM_PLAYER_STATE_READY:
463                         return "READY";
464                 case MM_PLAYER_STATE_PAUSED:
465                         return "PAUSED";
466                 case MM_PLAYER_STATE_PLAYING:
467                         return "PLAYING";
468                 case MM_PLAYER_STATE_NONE:
469                         return "NONE";
470                 default:
471                         return "INVAID";
472         }
473 }
474
475 gboolean
476 __is_rtsp_streaming ( mm_player_t* player )
477 {
478         return_val_if_fail ( player, FALSE );
479
480         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
481 }
482
483 gboolean
484 __is_wfd_streaming ( mm_player_t* player )
485 {
486   return_val_if_fail ( player, FALSE );
487
488   return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_WFD ) ? TRUE : FALSE;
489 }
490
491 gboolean
492 __is_http_streaming ( mm_player_t* player )
493 {
494         return_val_if_fail ( player, FALSE );
495
496         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
497 }
498
499 gboolean
500 __is_streaming ( mm_player_t* player )
501 {
502         return_val_if_fail ( player, FALSE );
503
504   return ( __is_http_progressive_down( player ) || __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player )
505           || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE;
506 }
507
508 gboolean
509 __is_live_streaming ( mm_player_t* player )
510 {
511         return_val_if_fail ( player, FALSE );
512
513         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
514 }
515
516 gboolean
517 __is_http_live_streaming( mm_player_t* player )
518 {
519         return_val_if_fail( player, FALSE );
520
521         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
522 }
523
524 gboolean
525 __is_dash_streaming ( mm_player_t* player )
526 {
527         return_val_if_fail ( player, FALSE );
528
529         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH ) ? TRUE : FALSE;
530 }
531
532 gboolean
533 __is_smooth_streaming ( mm_player_t* player )
534 {
535         return_val_if_fail ( player, FALSE );
536
537         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_SS ) ? TRUE : FALSE;
538 }
539
540
541 gboolean
542 __is_http_progressive_down(mm_player_t* player)
543 {
544         return_val_if_fail( player, FALSE );
545
546         return ((player->pd_mode) ? TRUE:FALSE);
547 }
548 /* if retval is FALSE, it will be dropped for perfomance. */
549 gboolean
550 __mmplayer_check_useful_message(mm_player_t *player, GstMessage * message)
551 {
552         gboolean retval = FALSE;
553
554         if ( !(player->pipeline && player->pipeline->mainbin) )
555         {
556                 debug_error("player pipeline handle is null");
557                 return TRUE;
558         }
559
560         switch (GST_MESSAGE_TYPE (message))
561         {
562                 case GST_MESSAGE_TAG:
563                 case GST_MESSAGE_EOS:
564                 case GST_MESSAGE_ERROR:
565                 case GST_MESSAGE_WARNING:
566                 case GST_MESSAGE_CLOCK_LOST:
567                 case GST_MESSAGE_NEW_CLOCK:
568                 case GST_MESSAGE_ELEMENT:
569                 case GST_MESSAGE_DURATION_CHANGED:
570                 case GST_MESSAGE_ASYNC_START:
571                         retval = TRUE;
572                         break;
573                 case GST_MESSAGE_ASYNC_DONE:
574                 case GST_MESSAGE_STATE_CHANGED:
575                         /* we only handle messages from pipeline */
576                         if(( message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) && (!player->gapless.reconfigure))
577                                 retval = TRUE;
578                         else
579                                 retval = FALSE;
580                         break;
581                 case GST_MESSAGE_BUFFERING:
582                 {
583                         gint buffer_percent = 0;
584
585                         gst_message_parse_buffering (message, &buffer_percent);
586
587                         if ((MMPLAYER_IS_STREAMING(player)) &&
588                                 (player->streamer) &&
589                                 (player->streamer->is_buffering == TRUE) &&
590                                 (buffer_percent == MAX_BUFFER_PERCENT))
591                         {
592                                 debug_log (">>> [%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
593                                 player->streamer->is_buffering_done = TRUE;
594                         }
595
596                         retval = TRUE;
597                         break;
598                 }
599                 default:
600                         retval = FALSE;
601                         break;
602         }
603
604         return retval;
605 }
606
607 gboolean
608 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
609 {
610         return_val_if_fail( player, FALSE );
611
612         if ( !player->msg_cb )
613         {
614                 return FALSE;
615         }
616
617         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
618
619         player->msg_cb(msgtype, param, player->msg_cb_param);
620
621         return TRUE;
622 }
623
624 gboolean
625 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
626 {
627         MMMessageParamType msg_param;
628         gchar *msg_src_element;
629
630         MMPLAYER_FENTER();
631
632         return_val_if_fail( player, FALSE );
633         return_val_if_fail( error, FALSE );
634
635         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
636
637         memset (&msg_param, 0, sizeof(MMMessageParamType));
638
639         if ( error->domain == GST_CORE_ERROR )
640         {
641                 msg_param.code = __gst_handle_core_error( player, error->code );
642         }
643         else if ( error->domain == GST_LIBRARY_ERROR )
644         {
645                 msg_param.code = __gst_handle_library_error( player, error->code );
646         }
647         else if ( error->domain == GST_RESOURCE_ERROR )
648         {
649                 msg_param.code = __gst_handle_resource_error( player, error->code );
650         }
651         else if ( error->domain == GST_STREAM_ERROR )
652         {
653                 msg_param.code = __gst_handle_stream_error( player, error, message );
654         }
655         else
656         {
657                 debug_warning("This error domain is not defined.\n");
658
659                 /* we treat system error as an internal error */
660                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
661         }
662
663         if ( message->src )
664         {
665                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
666
667                 msg_param.data = (void *) error->message;
668
669                 debug_error("-Msg src : [%s]    Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
670                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
671         }
672
673         /* no error */
674         if (msg_param.code == MM_ERROR_NONE)
675                 return TRUE;
676
677         /* post error to application */
678         if ( ! player->msg_posted )
679         {
680                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
681                 /* don't post more if one was sent already */
682                 player->msg_posted = TRUE;
683         }
684         else
685         {
686                 debug_log("skip error post because it's sent already.\n");
687         }
688
689         MMPLAYER_FLEAVE();
690
691         return TRUE;
692 }
693
694 gint
695 __gst_handle_core_error( mm_player_t* player, int code )
696 {
697         gint trans_err = MM_ERROR_NONE;
698
699         MMPLAYER_FENTER();
700
701         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
702
703         switch ( code )
704         {
705                 case GST_CORE_ERROR_MISSING_PLUGIN:
706                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
707                 case GST_CORE_ERROR_STATE_CHANGE:
708                 case GST_CORE_ERROR_SEEK:
709                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
710                 case GST_CORE_ERROR_FAILED:
711                 case GST_CORE_ERROR_TOO_LAZY:
712                 case GST_CORE_ERROR_PAD:
713                 case GST_CORE_ERROR_THREAD:
714                 case GST_CORE_ERROR_NEGOTIATION:
715                 case GST_CORE_ERROR_EVENT:
716                 case GST_CORE_ERROR_CAPS:
717                 case GST_CORE_ERROR_TAG:
718                 case GST_CORE_ERROR_CLOCK:
719                 case GST_CORE_ERROR_DISABLED:
720                 default:
721                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
722                 break;
723         }
724
725         MMPLAYER_FLEAVE();
726
727         return trans_err;
728 }
729
730 gint
731 __gst_handle_library_error( mm_player_t* player, int code )
732 {
733         gint trans_err = MM_ERROR_NONE;
734
735         MMPLAYER_FENTER();
736
737         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
738
739         switch ( code )
740         {
741                 case GST_LIBRARY_ERROR_FAILED:
742                 case GST_LIBRARY_ERROR_TOO_LAZY:
743                 case GST_LIBRARY_ERROR_INIT:
744                 case GST_LIBRARY_ERROR_SHUTDOWN:
745                 case GST_LIBRARY_ERROR_SETTINGS:
746                 case GST_LIBRARY_ERROR_ENCODE:
747                 default:
748                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
749                 break;
750         }
751
752         MMPLAYER_FLEAVE();
753
754         return trans_err;
755 }
756
757
758 gint
759 __gst_handle_resource_error( mm_player_t* player, int code )
760 {
761         gint trans_err = MM_ERROR_NONE;
762
763         MMPLAYER_FENTER();
764
765         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
766
767         switch ( code )
768         {
769                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
770                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
771                         break;
772                 case GST_RESOURCE_ERROR_NOT_FOUND:
773                 case GST_RESOURCE_ERROR_OPEN_READ:
774                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
775                                 || MMPLAYER_IS_RTSP_STREAMING(player))
776                         {
777                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
778                                 break;
779                         }
780                 case GST_RESOURCE_ERROR_READ:
781                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player )
782                                 || MMPLAYER_IS_RTSP_STREAMING(player))
783                         {
784                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
785                                 break;
786                         }
787                 case GST_RESOURCE_ERROR_WRITE:
788                 case GST_RESOURCE_ERROR_FAILED:
789                 case GST_RESOURCE_ERROR_SEEK:
790                 case GST_RESOURCE_ERROR_TOO_LAZY:
791                 case GST_RESOURCE_ERROR_BUSY:
792                 case GST_RESOURCE_ERROR_OPEN_WRITE:
793                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
794                 case GST_RESOURCE_ERROR_CLOSE:
795                 case GST_RESOURCE_ERROR_SYNC:
796                 case GST_RESOURCE_ERROR_SETTINGS:
797                 default:
798                         trans_err = MM_ERROR_PLAYER_INTERNAL;
799                 break;
800         }
801
802         MMPLAYER_FLEAVE();
803
804         return trans_err;
805 }
806
807
808 gint
809 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
810 {
811         gint trans_err = MM_ERROR_NONE;
812
813         MMPLAYER_FENTER();
814
815         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
816         return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
817         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
818
819         switch ( error->code )
820         {
821                 case GST_STREAM_ERROR_FAILED:
822                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
823                 case GST_STREAM_ERROR_DECODE:
824                 case GST_STREAM_ERROR_WRONG_TYPE:
825                 case GST_STREAM_ERROR_DECRYPT:
826                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
827                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
828                          trans_err = __gst_transform_gsterror( player, message, error );
829                 break;
830
831                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
832                 case GST_STREAM_ERROR_TOO_LAZY:
833                 case GST_STREAM_ERROR_ENCODE:
834                 case GST_STREAM_ERROR_DEMUX:
835                 case GST_STREAM_ERROR_MUX:
836                 case GST_STREAM_ERROR_FORMAT:
837                 default:
838                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
839                 break;
840         }
841
842         MMPLAYER_FLEAVE();
843
844         return trans_err;
845 }
846
847 /* NOTE : decide gstreamer state whether there is some playable track or not. */
848 static gint
849 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
850 {
851         gchar *src_element_name = NULL;
852         GstElement *src_element = NULL;
853         GstElementFactory *factory = NULL;
854         const gchar* klass = NULL;
855
856         MMPLAYER_FENTER();
857
858         /* FIXIT */
859         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
860         return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
861         return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
862
863         src_element = GST_ELEMENT_CAST(message->src);
864         if ( !src_element )
865                 goto INTERNAL_ERROR;
866
867         src_element_name = GST_ELEMENT_NAME(src_element);
868         if ( !src_element_name )
869                 goto INTERNAL_ERROR;
870
871         factory = gst_element_get_factory(src_element);
872         if ( !factory )
873                 goto INTERNAL_ERROR;
874
875         klass = gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
876         if ( !klass )
877                 goto INTERNAL_ERROR;
878
879         debug_log("error code=%d, msg=%s, src element=%s, class=%s\n",
880                         error->code, error->message, src_element_name, klass);
881
882         //<-
883         {
884                 if (player->selector) {
885                         int msg_src_pos = 0;
886                         gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
887                         debug_log ("current  active pad index  -%d", active_pad_index);
888
889                         if  (src_element_name) {
890                                 int idx = 0;
891
892                                 if (player->audio_decoders) {
893                                         GList *adec = player->audio_decoders;
894                                         for ( ;adec ; adec = g_list_next(adec)) {
895                                                 gchar *name = adec->data;
896
897                                                 debug_log("found audio decoder name  = %s", name);
898                                                 if (g_strrstr(name, src_element_name)) {
899                                                         msg_src_pos = idx;
900                                                         break;
901                                                 }
902                                                 idx++;
903                                         }
904                                 }
905                                 debug_log("active pad = %d, error src index = %d", active_pad_index,  msg_src_pos);
906                         }
907
908                         if (active_pad_index != msg_src_pos) {
909                                 debug_log("skip error because error is posted from no activated track");
910                                 return MM_ERROR_NONE;
911                         }
912                 }
913         }
914         //-> temp code
915
916         switch ( error->code )
917         {
918                 case GST_STREAM_ERROR_DECODE:
919                 {
920                         /* Demuxer can't parse one track because it's corrupted.
921                          * So, the decoder for it is not linked.
922                          * But, it has one playable track.
923                          */
924                         if ( g_strrstr(klass, "Demux") )
925                         {
926                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
927                                 {
928                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
929                                 }
930                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
931                                 {
932                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
933                                 }
934                                 else
935                                 {
936                                         if ( player->pipeline->audiobin ) // PCM
937                                         {
938                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
939                                         }
940                                         else
941                                         {
942                                                 goto CODEC_NOT_FOUND;
943                                         }
944                                 }
945                         }
946                         return MM_ERROR_PLAYER_INVALID_STREAM;
947                 }
948                 break;
949
950                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
951                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
952                 case GST_STREAM_ERROR_WRONG_TYPE:
953                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
954
955                 case GST_STREAM_ERROR_FAILED:
956                 {
957                         /* Decoder Custom Message */
958                         if ( strstr(error->message, "ongoing") )
959                         {
960                                 if ( strncasecmp(klass, "audio", 5) )
961                                 {
962                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
963                                         {
964                                                 debug_log("Video can keep playing.\n");
965                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
966                                         }
967                                         else
968                                         {
969                                                 goto CODEC_NOT_FOUND;
970                                         }
971
972                                 }
973                                 else if ( strncasecmp(klass, "video", 5) )
974                                 {
975                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
976                                         {
977                                                 debug_log("Audio can keep playing.\n");
978                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
979                                         }
980                                         else
981                                         {
982                                                 goto CODEC_NOT_FOUND;
983                                         }
984                                 }
985                         }
986                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
987                 }
988                 break;
989
990                 case GST_STREAM_ERROR_DECRYPT:
991                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
992                 {
993                         debug_error("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
994
995                         if ( strstr(error->message, "rights expired") )
996                         {
997                                 return MM_ERROR_PLAYER_DRM_EXPIRED;
998                         }
999                         else if ( strstr(error->message, "no rights") )
1000                         {
1001                                 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
1002                         }
1003                         else if ( strstr(error->message, "has future rights") )
1004                         {
1005                                 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
1006                         }
1007                         else if ( strstr(error->message, "opl violation") )
1008                         {
1009                                 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
1010                         }
1011                         return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
1012                 }
1013                 break;
1014
1015                 default:
1016                 break;
1017         }
1018
1019         MMPLAYER_FLEAVE();
1020
1021         return MM_ERROR_PLAYER_INVALID_STREAM;
1022
1023 INTERNAL_ERROR:
1024         return MM_ERROR_PLAYER_INTERNAL;
1025
1026 CODEC_NOT_FOUND:
1027         debug_log("not found any available codec. Player should be destroyed.\n");
1028         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
1029 }
1030
1031 static gboolean
1032 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
1033 {
1034         int pro_value = 0; // in the case of expection, default will be returned.
1035         int dest_angle = rotation_angle;
1036         int rotation_type = -1;
1037         #define ROTATION_USING_SINK 0
1038         #define ROTATION_USING_CUSTOM 1
1039         #define ROTATION_USING_FLIP     2
1040
1041         return_val_if_fail(player, FALSE);
1042         return_val_if_fail(value, FALSE);
1043         return_val_if_fail(rotation_angle >= 0, FALSE);
1044
1045         if (rotation_angle >= 360)
1046         {
1047                 dest_angle = rotation_angle - 360;
1048         }
1049
1050         /* chech if supported or not */
1051         if ( dest_angle % 90 )
1052         {
1053                 debug_log("not supported rotation angle = %d", rotation_angle);
1054                 return FALSE;
1055         }
1056
1057         /*
1058           * xvimagesink only     (A)
1059           * custom_convert - no xv (e.g. memsink, evasimagesink  (B)
1060           * videoflip - avsysmemsink (C)
1061           */
1062         if (player->set_mode.video_zc)
1063         {
1064                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
1065                 {
1066                         rotation_type = ROTATION_USING_CUSTOM;
1067                 }
1068                 else // A
1069                 {
1070                         rotation_type = ROTATION_USING_SINK;
1071                 }
1072         }
1073         else
1074         {
1075                 int surface_type = 0;
1076                 rotation_type = ROTATION_USING_FLIP;
1077
1078                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
1079                 debug_log("check display surface type attribute: %d", surface_type);
1080
1081                 if ((surface_type == MM_DISPLAY_SURFACE_X) ||
1082                         (surface_type == MM_DISPLAY_SURFACE_EVAS && !strcmp(player->ini.videosink_element_evas, "evaspixmapsink")))
1083                 {
1084                         rotation_type = ROTATION_USING_SINK;
1085                 }
1086                 else
1087                 {
1088                         rotation_type = ROTATION_USING_FLIP; //C
1089                 }
1090
1091                 debug_log("using %d type for rotation", rotation_type);
1092         }
1093
1094         /* get property value for setting */
1095         switch(rotation_type)
1096         {
1097                 case ROTATION_USING_SINK: // xvimagesink, pixmap
1098                         {
1099                                 switch (dest_angle)
1100                                 {
1101                                         case 0:
1102                                                 break;
1103                                         case 90:
1104                                                 pro_value = 3; // clockwise 90
1105                                                 break;
1106                                         case 180:
1107                                                 pro_value = 2;
1108                                                 break;
1109                                         case 270:
1110                                                 pro_value = 1; // counter-clockwise 90
1111                                                 break;
1112                                 }
1113                         }
1114                         break;
1115                 case ROTATION_USING_CUSTOM:
1116                         {
1117                                 gchar *ename = NULL;
1118                                 ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1119
1120                                 if (g_strrstr(ename, "fimcconvert"))
1121                                 {
1122                                         switch (dest_angle)
1123                                         {
1124                                                 case 0:
1125                                                         break;
1126                                                 case 90:
1127                                                         pro_value = 90; // clockwise 90
1128                                                         break;
1129                                                 case 180:
1130                                                         pro_value = 180;
1131                                                         break;
1132                                                 case 270:
1133                                                         pro_value = 270; // counter-clockwise 90
1134                                                         break;
1135                                         }
1136                                 }
1137                         }
1138                         break;
1139                 case ROTATION_USING_FLIP: // videoflip
1140                         {
1141                                         switch (dest_angle)
1142                                         {
1143
1144                                                 case 0:
1145                                                         break;
1146                                                 case 90:
1147                                                         pro_value = 1; // clockwise 90
1148                                                         break;
1149                                                 case 180:
1150                                                         pro_value = 2;
1151                                                         break;
1152                                                 case 270:
1153                                                         pro_value = 3; // counter-clockwise 90
1154                                                         break;
1155                                         }
1156                         }
1157                         break;
1158         }
1159
1160         debug_log("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
1161
1162         *value = pro_value;
1163
1164         return TRUE;
1165 }
1166
1167 int
1168 _mmplayer_update_video_param(mm_player_t* player) // @
1169 {
1170         MMHandleType attrs = 0;
1171         int surface_type = 0;
1172         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
1173         int user_angle = 0;
1174         int user_angle_type= 0;
1175         int rotation_value = 0;
1176         gchar *org_orient = NULL;
1177
1178         MMPLAYER_FENTER();
1179
1180         /* check video sinkbin is created */
1181         return_val_if_fail ( player &&
1182                 player->pipeline &&
1183                 player->pipeline->videobin &&
1184                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
1185                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1186                 MM_ERROR_PLAYER_NOT_INITIALIZED );
1187
1188         attrs = MMPLAYER_GET_ATTRS(player);
1189         if ( !attrs )
1190         {
1191                 debug_error("cannot get content attribute");
1192                 return MM_ERROR_PLAYER_INTERNAL;
1193         }
1194
1195         /* update user roation */
1196         mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
1197
1198         /* get angle with user type */
1199         switch(user_angle_type)
1200         {
1201                 case MM_DISPLAY_ROTATION_NONE:
1202                         user_angle = 0;
1203                         break;
1204                 case MM_DISPLAY_ROTATION_90: // counter-clockwise 90
1205                         user_angle = 270;
1206                         break;
1207                 case MM_DISPLAY_ROTATION_180:
1208                         user_angle = 180;
1209                         break;
1210                 case MM_DISPLAY_ROTATION_270: // clockwise 90
1211                         user_angle = 90;
1212                         break;
1213         }
1214
1215         /* get original orientation */
1216         mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
1217
1218         if (org_orient)
1219         {
1220                 if (!strcmp (org_orient, "rotate-90"))
1221                         org_angle = 90;
1222                 else if (!strcmp (org_orient, "rotate-180"))
1223                         org_angle = 180;
1224                 else if (!strcmp (org_orient, "rotate-270"))
1225                         org_angle = 270;
1226                 else
1227                         debug_log ("original rotation is %s", org_orient);
1228         }
1229         else
1230         {
1231                 debug_log ("content_video_orientation get fail");
1232         }
1233
1234         debug_log("check user angle: %d, orientation: %d", user_angle, org_angle);
1235
1236         /* check video stream callback is used */
1237         if(!player->set_mode.media_packet_video_stream && player->use_video_stream )
1238         {
1239                 if (player->set_mode.video_zc)
1240                 {
1241                         gchar *ename = NULL;
1242                         int width = 0;
1243                         int height = 0;
1244
1245                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
1246                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
1247
1248                         /* resize video frame with requested values for fimcconvert */
1249                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
1250
1251                         if (ename && g_strrstr(ename, "fimcconvert"))
1252                         {
1253                                 if (width)
1254                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1255
1256                                 if (height)
1257                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1258
1259                                 /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
1260                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
1261
1262                                 /* get rotation value to set */
1263                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1264
1265                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "rotate", rotation_value, NULL);
1266
1267                                 debug_log("updating fimcconvert - r[%d], w[%d], h[%d]", rotation_value, width, height);
1268                         }
1269                 }
1270                 else
1271                 {
1272                         debug_log("using video stream callback with memsink. player handle : [%p]", player);
1273
1274                         /* get rotation value to set */
1275                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1276
1277                         g_object_set(player->pipeline->videobin[MMPLAYER_V_FLIP].gst, "method", rotation_value, NULL);
1278                 }
1279
1280                 return MM_ERROR_NONE;
1281         }
1282
1283         /* update display surface */
1284         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
1285         debug_log("check display surface type attribute: %d", surface_type);
1286
1287         /* configuring display */
1288         switch ( surface_type )
1289         {
1290                 case MM_DISPLAY_SURFACE_X:
1291                 {
1292                         /* ximagesink or xvimagesink */
1293                         void *surface = NULL;
1294                         int display_method = 0;
1295                         int roi_x = 0;
1296                         int roi_y = 0;
1297                         int roi_w = 0;
1298                         int roi_h = 0;
1299                         int src_crop_x = 0;
1300                         int src_crop_y = 0;
1301                         int src_crop_w = 0;
1302                         int src_crop_h = 0;
1303                         int force_aspect_ratio = 0;
1304                         gboolean visible = TRUE;
1305
1306 #ifdef HAVE_WAYLAND
1307                         /*set wl_display*/
1308                         void* wl_display = NULL;
1309                         GstContext *context = NULL;
1310                         int wl_window_x = 0;
1311                         int wl_window_y = 0;
1312                         int wl_window_width = 0;
1313                         int wl_window_height = 0;
1314
1315                         mm_attrs_get_data_by_name(attrs, "wl_display", &wl_display);
1316                         if (wl_display)
1317                                 context = gst_wayland_display_handle_context_new(wl_display);
1318                         if (context)
1319                                 gst_element_set_context(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), context);
1320
1321                         /*It should be set after setting window*/
1322                         mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
1323                         mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
1324                         mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
1325                         mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
1326 #endif
1327                         /* common case if using x surface */
1328                         mm_attrs_get_data_by_name(attrs, "display_overlay", &surface);
1329                         if ( surface )
1330                         {
1331 #ifdef HAVE_WAYLAND
1332                                 guintptr wl_surface = (guintptr)surface;
1333                                 debug_log("set video param : wayland surface %p", surface);
1334                                 gst_video_overlay_set_window_handle(
1335                                                 GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ),
1336                                                 wl_surface );
1337                                 /* After setting window handle, set render      rectangle */
1338                                 gst_video_overlay_set_render_rectangle(
1339                                          GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ),
1340                                          wl_window_x,wl_window_y,wl_window_width,wl_window_height);
1341 #else // HAVE_X11
1342                                 int xwin_id = 0;
1343                                 xwin_id = *(int*)surface;
1344                                 debug_log("set video param : xid %p", *(int*)surface);
1345                                 if (xwin_id)
1346                                 {
1347                                         gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)surface );
1348                                 }
1349 #endif
1350                         }
1351                         else
1352                         {
1353                                 /* FIXIT : is it error case? */
1354                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
1355                         }
1356
1357                         /* if xvimagesink */
1358                         if (!strcmp(player->ini.videosink_element_x,"xvimagesink"))
1359                         {
1360                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
1361                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1362                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_x", &src_crop_x);
1363                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_y", &src_crop_y);
1364                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_width", &src_crop_w);
1365                                 mm_attrs_get_int_by_name(attrs, "display_src_crop_height", &src_crop_h);
1366                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1367                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1368                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1369                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1370                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1371                                 #define DEFAULT_DISPLAY_MODE    2       // TV only, PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN
1372
1373                                 /* setting for cropping media source */
1374                                 if (src_crop_w && src_crop_h)
1375                                 {
1376                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1377                                                 "src-crop-x", src_crop_x,
1378                                                 "src-crop-y", src_crop_y,
1379                                                 "src-crop-w", src_crop_w,
1380                                                 "src-crop-h", src_crop_h,
1381                                                 NULL );
1382                                 }
1383
1384                                 /* setting for ROI mode */
1385                                 if (display_method == 5)        // 5 for ROI mode
1386                                 {
1387                                         int roi_mode = 0;
1388                                         mm_attrs_get_int_by_name(attrs, "display_roi_mode", &roi_mode);
1389                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1390                                                 "dst-roi-mode", roi_mode,
1391                                                 "dst-roi-x", roi_x,
1392                                                 "dst-roi-y", roi_y,
1393                                                 "dst-roi-w", roi_w,
1394                                                 "dst-roi-h", roi_h,
1395                                                 NULL );
1396                                         /* get rotation value to set,
1397                                            do not use org_angle because ROI mode in xvimagesink needs both a rotation value and an orientation value */
1398                                         __mmplayer_get_property_value_for_rotation(player, user_angle, &rotation_value);
1399                                 }
1400                                 else
1401                                 {
1402                                         /* get rotation value to set */
1403                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1404                                 }
1405
1406                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1407                                         "force-aspect-ratio", force_aspect_ratio,
1408                                         "orientation", org_angle/90, // setting for orientation of media, it is used for ROI/ZOOM feature in xvimagesink
1409                                         "rotate", rotation_value,
1410                                         "handle-events", TRUE,
1411                                         "display-geometry-method", display_method,
1412                                         "draw-borders", FALSE,
1413                                         "handle-expose", FALSE,
1414                                         "visible", visible,
1415                                         "display-mode", DEFAULT_DISPLAY_MODE,
1416                                         NULL );
1417
1418                                 debug_log("set video param : rotate %d, method %d visible %d", rotation_value, display_method, visible);
1419                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d", roi_x, roi_y, roi_w, roi_h );
1420                                 debug_log("set video param : force aspect ratio %d, display mode %d", force_aspect_ratio, DEFAULT_DISPLAY_MODE);
1421                         }
1422                 }
1423                 break;
1424                 case MM_DISPLAY_SURFACE_EVAS:
1425                 {
1426                         void *object = NULL;
1427                         int scaling = 0;
1428                         gboolean visible = TRUE;
1429                         int display_method = 0;
1430
1431                         /* common case if using evas surface */
1432                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
1433                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1434                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
1435                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1436
1437                         /* if evasimagesink */
1438                         if (!strcmp(player->ini.videosink_element_evas,"evasimagesink"))
1439                         {
1440                                 if (object)
1441                                 {
1442                                         /* if it is evasimagesink, we are not supporting rotation */
1443                                         if (user_angle_type!=MM_DISPLAY_ROTATION_NONE)
1444                                         {
1445                                                 mm_attrs_set_int_by_name(attrs, "display_rotation", MM_DISPLAY_ROTATION_NONE);
1446                                                 if (mmf_attrs_commit (attrs)) /* return -1 if error */
1447                                                         debug_error("failed to commit\n");
1448                                                 debug_warning("unsupported feature");
1449                                                 return MM_ERROR_NOT_SUPPORT_API;
1450                                         }
1451                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1452                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1453                                                         "evas-object", object,
1454                                                         "visible", visible,
1455                                                         "display-geometry-method", display_method,
1456                                                         "rotate", rotation_value,
1457                                                         NULL);
1458                                         debug_log("set video param : method %d", display_method);
1459                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
1460                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
1461                                 }
1462                                 else
1463                                 {
1464                                         debug_error("no evas object");
1465                                         return MM_ERROR_PLAYER_INTERNAL;
1466                                 }
1467
1468
1469                                 /* if evasimagesink using converter */
1470                                 if (player->set_mode.video_zc && player->pipeline->videobin[MMPLAYER_V_CONV].gst)
1471                                 {
1472                                         int width = 0;
1473                                         int height = 0;
1474                                         int no_scaling = !scaling;
1475
1476                                         mm_attrs_get_int_by_name(attrs, "display_width", &width);
1477                                         mm_attrs_get_int_by_name(attrs, "display_height", &height);
1478
1479                                         /* NOTE: fimcconvert does not manage index of src buffer from upstream src-plugin, decoder gives frame information in output buffer with no ordering */
1480                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "src-rand-idx", TRUE, NULL);
1481                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-buffer-num", 5, NULL);
1482
1483                                         if (no_scaling)
1484                                         {
1485                                                 /* no-scaling order to fimcconvert, original width, height size of media src will be passed to sink plugin */
1486                                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst,
1487                                                                 "dst-width", 0, /* setting 0, output video width will be media src's width */
1488                                                                 "dst-height", 0, /* setting 0, output video height will be media src's height */
1489                                                                 NULL);
1490                                         }
1491                                         else
1492                                         {
1493                                                 /* scaling order to fimcconvert */
1494                                                 if (width)
1495                                                 {
1496                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-width", width, NULL);
1497                                                 }
1498                                                 if (height)
1499                                                 {
1500                                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_CONV].gst, "dst-height", height, NULL);
1501                                                 }
1502                                                 debug_log("set video param : video frame scaling down to width(%d) height(%d)", width, height);
1503                                         }
1504                                         debug_log("set video param : display_evas_do_scaling %d", scaling);
1505                                 }
1506                         }
1507
1508                         /* if evaspixmapsink */
1509                         if (!strcmp(player->ini.videosink_element_evas,"evaspixmapsink"))
1510                         {
1511                                 if (object)
1512                                 {
1513                                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1514                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1515                                                         "evas-object", object,
1516                                                         "visible", visible,
1517                                                         "display-geometry-method", display_method,
1518                                                         "rotate", rotation_value,
1519                                                         NULL);
1520                                         debug_log("set video param : method %d", display_method);
1521                                         debug_log("set video param : evas-object %x, visible %d", object, visible);
1522                                         debug_log("set video param : evas-object %x, rotate %d", object, rotation_value);
1523                                 }
1524                                 else
1525                                 {
1526                                         debug_error("no evas object");
1527                                         return MM_ERROR_PLAYER_INTERNAL;
1528                                 }
1529
1530                                 int display_method = 0;
1531                                 int roi_x = 0;
1532                                 int roi_y = 0;
1533                                 int roi_w = 0;
1534                                 int roi_h = 0;
1535                                 int origin_size = !scaling;
1536
1537                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1538                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
1539                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
1540                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
1541                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
1542
1543                                 /* get rotation value to set */
1544                                 __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1545
1546                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1547                                         "origin-size", origin_size,
1548                                         "rotate", rotation_value,
1549                                         "dst-roi-x", roi_x,
1550                                         "dst-roi-y", roi_y,
1551                                         "dst-roi-w", roi_w,
1552                                         "dst-roi-h", roi_h,
1553                                         "display-geometry-method", display_method,
1554                                         NULL );
1555
1556                                 debug_log("set video param : method %d", display_method);
1557                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
1558                                                                 roi_x, roi_y, roi_w, roi_h );
1559                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
1560                         }
1561                 }
1562                 break;
1563                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is used for the videoTexture(canvasTexture) overlay */
1564                 {
1565                         void *pixmap_id_cb = NULL;
1566                         void *pixmap_id_cb_user_data = NULL;
1567                         int display_method = 0;
1568                         gboolean visible = TRUE;
1569
1570                         /* if xvimagesink */
1571                         if (strcmp(player->ini.videosink_element_x,"xvimagesink"))
1572                         {
1573                                 debug_error("videosink is not xvimagesink");
1574                                 return MM_ERROR_PLAYER_INTERNAL;
1575                         }
1576
1577                         /* get information from attributes */
1578                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
1579                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
1580                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1581                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1582
1583                         if ( pixmap_id_cb )
1584                         {
1585                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
1586                                 if (pixmap_id_cb_user_data)
1587                                 {
1588                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
1589                                 }
1590                         }
1591                         else
1592                         {
1593                                 debug_error("failed to set pixmap-id-callback");
1594                                 return MM_ERROR_PLAYER_INTERNAL;
1595                         }
1596                         /* get rotation value to set */
1597                         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
1598
1599                         debug_log("set video param : rotate %d, method %d, visible %d", rotation_value, display_method, visible);
1600
1601                         /* set properties of videosink plugin */
1602                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1603                                 "display-geometry-method", display_method,
1604                                 "draw-borders", FALSE,
1605                                 "visible", visible,
1606                                 "rotate", rotation_value,
1607                                 "pixmap-id-callback", pixmap_id_cb,
1608                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
1609                                 NULL );
1610                 }
1611                 break;
1612                 case MM_DISPLAY_SURFACE_NULL:
1613                 {
1614                         /* do nothing */
1615                 }
1616                 break;
1617                 case MM_DISPLAY_SURFACE_REMOTE:
1618                 {
1619                         /* do nothing */
1620                 }
1621                 break;
1622         }
1623
1624         MMPLAYER_FLEAVE();
1625
1626         return MM_ERROR_NONE;
1627 }
1628
1629
1630
1631 int _mmplayer_set_shm_stream_path(MMHandleType hplayer, const char *path)
1632 {
1633         mm_player_t* player = (mm_player_t*) hplayer;
1634         int result;
1635
1636         MMPLAYER_FENTER();
1637
1638         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
1639         return_val_if_fail(path, MM_ERROR_INVALID_ARGUMENT);
1640
1641         result = mm_attrs_set_string_by_name(player->attrs, "shm_stream_path", path)
1642
1643         MMPLAYER_FLEAVE();
1644         return result;
1645 }