[0.6.205] sort codec factory by user request 58/215158/5 accepted/tizen/unified/20191006.223651 submit/tizen/20191004.024448
authorEunhye Choi <eunhae1.choi@samsung.com>
Wed, 2 Oct 2019 05:35:47 +0000 (14:35 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Wed, 2 Oct 2019 08:37:46 +0000 (17:37 +0900)
- sort codec elements instead of skip it during auto-plugging.
- to handle the unsupported media format with default type decoder
  the other type decoder should be added.

Change-Id: I80aea47412e6230f8677bc8ffc66874d325d5e05

packaging/libmm-player.spec
src/include/mm_player_priv.h
src/mm_player_gst.c
src/mm_player_priv.c

index 94c15dc..4b0d878 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-player
 Summary:    Multimedia Framework Player Library
-Version:    0.6.204
+Version:    0.6.205
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index c74063f..5431dfd 100644 (file)
@@ -635,6 +635,8 @@ typedef struct {
        gboolean no_more_pad;
        gint num_dynamic_pad;
        gboolean has_many_types;
+       gboolean need_audio_dec_sorting;
+       gboolean need_video_dec_sorting;
 
        /* progress callback timer */
        /* FIXIT : since duplicated functionality with get_position
@@ -878,6 +880,7 @@ gboolean _mmplayer_gst_remove_fakesink(mmplayer_t *player, mmplayer_gst_element_
 void _mmplayer_add_signal_connection(mmplayer_t *player, GObject *object, mmplayer_signal_type_e type, const gchar *signal, GCallback cb_funct, gpointer u_data);
 void _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data);
 gint _mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad *pad, GstCaps *caps, GstElementFactory *factory, gpointer data);
+GValueArray *_mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad *pad, GstCaps *caps, GValueArray *factories, gpointer data);
 gboolean _mmplayer_gst_create_decoder(mmplayer_t *player, GstPad *srcpad, const GstCaps *caps);
 void _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data);
 GstElement *_mmplayer_gst_make_decodebin(mmplayer_t *player);
index b2dd971..79af3f2 100644 (file)
@@ -2295,6 +2295,10 @@ __mmplayer_gst_create_es_decoder(mmplayer_t *player, mmplayer_stream_type_e type
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
                                                                                G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
 
+       if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
+               _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
+                                                       G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
+
        /* This signal is emitted when a element is added to the bin.*/
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
                                                                                G_CALLBACK(_mmplayer_gst_element_added), (gpointer)player);
index 08c11fb..6f1a7d6 100644 (file)
@@ -4947,11 +4947,13 @@ int
 _mmplayer_realize(MMHandleType hplayer)
 {
        mmplayer_t *player = (mmplayer_t *)hplayer;
+       int ret = MM_ERROR_NONE;
        char *uri = NULL;
        void *param = NULL;
        MMHandleType attrs = 0;
-       int ret = MM_ERROR_NONE;
-
+       int video_codec_type = 0;
+       int audio_codec_type = 0;
+       int default_codec_type = 0;
        MMPLAYER_FENTER();
 
        /* check player handle */
@@ -5035,6 +5037,23 @@ _mmplayer_realize(MMHandleType hplayer)
                                                                player->streamer->buffering_req.rebuffer_time);
        }
 
+       mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
+       if (!strcmp(player->ini.audiocodec_default_type, "hw"))
+               default_codec_type = MM_PLAYER_CODEC_TYPE_HW;
+       else
+               default_codec_type = MM_PLAYER_CODEC_TYPE_SW;
+
+       if (audio_codec_type != default_codec_type) {
+               LOGD("audio dec sorting is required");
+               player->need_audio_dec_sorting = TRUE;
+       }
+
+       mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
+       if (video_codec_type != MM_PLAYER_CODEC_TYPE_DEFAULT) {
+               LOGD("video dec sorting is required");
+               player->need_video_dec_sorting = TRUE;
+       }
+
        /* realize pipeline */
        ret = __mmplayer_gst_realize(player);
        if (ret != MM_ERROR_NONE)
@@ -5937,6 +5956,10 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player)
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
                                                G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player);
 
+       if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
+               _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
+                                                       G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
+
        /* This signal is emitted whenever decodebin finds a new stream. It is emitted
           before looking for any elements that can handle that stream.*/
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
@@ -6941,8 +6964,6 @@ static GstAutoplugSelectResult
 __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps, char *factory_name)
 {
        GstAutoplugSelectResult ret = GST_AUTOPLUG_SELECT_TRY;
-       int idx = 0;
-       int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
        int audio_offload = 0;
 
        if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
@@ -6964,28 +6985,6 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps
                                  And need to consider the multi-track audio content.
                          There is no HW audio decoder in public. */
 
-               mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
-
-               LOGD("audio codec type: %d", codec_type);
-               if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
-                       /* sw codec will be skipped */
-                       for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) {
-                               if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) {
-                                       LOGW("skipping sw acodec:[%s] by codec type", factory_name);
-                                       ret = GST_AUTOPLUG_SELECT_SKIP;
-                                       goto DONE;
-                               }
-                       }
-               } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
-                       /* hw codec will be skipped */
-                       if (strcmp(player->ini.audiocodec_element_hw, "") &&
-                           g_strrstr(factory_name, player->ini.audiocodec_element_hw)) {
-                               LOGW("skipping hw acodec:[%s] by codec type", factory_name);
-                               ret = GST_AUTOPLUG_SELECT_SKIP;
-                               goto DONE;
-                       }
-               }
-
                /* set stream information */
                if (!player->audiodec_linked)
                        __mmplayer_set_audio_attrs(player, caps);
@@ -6997,27 +6996,6 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps
 
        } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
 
-               mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
-
-               LOGD("video codec type: %d", codec_type);
-               if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
-                       /* sw codec is skipped */
-                       for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) {
-                               if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) {
-                                       LOGW("skipping sw vcodec:[%s] by codec type", factory_name);
-                                       ret = GST_AUTOPLUG_SELECT_SKIP;
-                                       goto DONE;
-                               }
-                       }
-               } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
-                       /* hw codec is skipped */
-                       if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
-                               LOGW("skipping hw vcodec:[%s] by codec type", factory_name);
-                               ret = GST_AUTOPLUG_SELECT_SKIP;
-                               goto DONE;
-                       }
-               }
-
                if ((strlen(player->ini.videocodec_element_hw) > 0) &&
                        (g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
 
@@ -7046,6 +7024,120 @@ DONE:
        return ret;
 }
 
+GValueArray *
+_mmplayer_gst_decode_autoplug_sort(GstElement *bin,
+               GstPad *pad, GstCaps *caps, GValueArray *factories, gpointer data)
+{
+#define DEFAULT_IDX 0xFFFF
+#define MIN_FACTORY_NUM 2
+       mmplayer_t *player = (mmplayer_t *)data;
+       GValueArray *new_factories = NULL;
+       GValue val = { 0, };
+       GstElementFactory *factory = NULL;
+       const gchar *klass = NULL;
+       gchar *factory_name = NULL;
+       guint hw_dec_idx = DEFAULT_IDX;
+       guint first_sw_dec_idx = DEFAULT_IDX;
+       guint last_sw_dec_idx = DEFAULT_IDX;
+       guint new_pos = DEFAULT_IDX;
+       guint rm_pos = DEFAULT_IDX;
+       int audio_codec_type;
+       int video_codec_type;
+       mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+
+       if (factories->n_values < MIN_FACTORY_NUM)
+               return NULL;
+
+       mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
+       mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
+
+#ifdef __DEBUG__
+       LOGD("num of factory : %d, codec type %d, %d", factories->n_values, video_codec_type, audio_codec_type);
+#endif
+       for (int i = 0 ; i < factories->n_values ; i++) {
+               gchar *hw_dec_info = NULL;
+               gchar (*sw_dec_info)[PLAYER_INI_MAX_STRLEN] = {NULL, };
+
+               factory = g_value_get_object(g_value_array_get_nth(factories, i));
+               klass = gst_element_factory_get_klass(factory);
+               factory_name = GST_OBJECT_NAME(factory);
+
+#ifdef __DEBUG__
+               LOGD("Klass [%s] Factory [%s]", klass, factory_name);
+#endif
+               if (g_strrstr(klass, "Codec/Decoder/Audio")) {
+                       if (!player->need_audio_dec_sorting) {
+                               LOGD("sorting is not required");
+                               return NULL;
+                       }
+                       codec_type = audio_codec_type;
+                       hw_dec_info = player->ini.audiocodec_element_hw;
+                       sw_dec_info = player->ini.audiocodec_element_sw;
+               } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
+                       if (!player->need_video_dec_sorting) {
+                               LOGD("sorting is not required");
+                               return NULL;
+                       }
+                       codec_type = video_codec_type;
+                       hw_dec_info = player->ini.videocodec_element_hw;
+                       sw_dec_info = player->ini.videocodec_element_sw;
+               } else {
+                       continue;
+               }
+
+               if (g_strrstr(factory_name, hw_dec_info)) {
+                       hw_dec_idx = i;
+               } else {
+                       for (int j = 0; sw_dec_info[j][0] != '\0'; j++) {
+                               if (strstr(factory_name, sw_dec_info[j])) {
+                                       last_sw_dec_idx = i;
+                                       if (first_sw_dec_idx == DEFAULT_IDX) {
+                                               first_sw_dec_idx = i;
+                                       }
+                               }
+                       }
+
+                       if (first_sw_dec_idx == DEFAULT_IDX)
+                               LOGW("unknown codec %s", factory_name);
+               }
+       }
+
+       if (hw_dec_idx == DEFAULT_IDX || first_sw_dec_idx == DEFAULT_IDX)
+               return NULL;
+
+       if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
+               if (hw_dec_idx < first_sw_dec_idx)
+                       return NULL;
+               new_pos = first_sw_dec_idx - 1;
+               rm_pos = hw_dec_idx + 1;
+       } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
+               if (last_sw_dec_idx < hw_dec_idx)
+                       return NULL;
+               new_pos = last_sw_dec_idx + 1;
+               rm_pos = hw_dec_idx;
+       } else {
+               return NULL;
+       }
+
+       /* change position - insert H/W decoder according to the new position */
+       new_factories = g_value_array_copy(factories);
+       factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx));
+       g_value_init (&val, G_TYPE_OBJECT);
+       g_value_set_object (&val, factory);
+       g_value_array_insert(new_factories, new_pos, &val);
+       g_value_unset (&val);
+       g_value_array_remove(new_factories, rm_pos);    /* remove previous H/W element */
+
+       for (int i = 0 ; i < new_factories->n_values ; i++) {
+               factory = g_value_get_object(g_value_array_get_nth(new_factories, i));
+
+               LOGD("[Re-arranged] Klass [%s] Factory [%s]",
+                       gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory));
+       }
+
+       return new_factories;
+}
+
 gint
 _mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad *pad,
        GstCaps *caps, GstElementFactory *factory, gpointer data)