support playback with sw codec 59/230659/7
authorEunhye Choi <eunhae1.choi@samsung.com>
Mon, 13 Apr 2020 07:49:27 +0000 (16:49 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Mon, 13 Apr 2020 11:12:22 +0000 (20:12 +0900)
- support setting decoder type
- handle request-resource signal
- update stream attr in select-stream signal
  instead of autoplug-select signal which is not
  emitted in decodebin3.

Change-Id: I235683d76ce90fe95b3fb57575116bd5b16316e7

src/include/mm_player_priv.h
src/mm_player_gst.c
src/mm_player_priv.c

index a440e6c..1f321f1 100644 (file)
@@ -905,6 +905,8 @@ void _mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
 void _mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data);
 gboolean _mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer data);
 void _mmplayer_pipeline_complete(GstElement *decodebin, gpointer data);
+void _mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps);
+int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type);
 
 #ifdef __cplusplus
        }
index c864487..bb16882 100644 (file)
@@ -2892,47 +2892,143 @@ __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, g
        MMPLAYER_FLEAVE();
 }
 
-gint __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
+static gint
+__mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
     GstStream * stream, gpointer data)
 {
-       GstStreamType stype = gst_stream_get_stream_type (stream);
+       gint ret = 0; /* 1: select, 0: skip, -1: depends on decodebin */
+       GstStreamType stype = gst_stream_get_stream_type(stream);
        mmplayer_t *player = (mmplayer_t *)data;
        mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_MAX;
+       GstCaps *caps = gst_stream_get_caps(stream);
+       gchar *caps_str = NULL;
 
-       if (stype & GST_STREAM_TYPE_AUDIO) {
-               LOGW("AUDIO type 0x%X", stype);
-               type = MM_PLAYER_TRACK_TYPE_AUDIO;
+       LOGD("Stream type %s flags 0x%x",
+                       gst_stream_type_get_name(stype),
+                       gst_stream_get_stream_flags(stream));
+       LOGD("  ID: %s", gst_stream_get_stream_id(stream));
+
+       if (caps) {
+               caps_str = gst_caps_to_string(caps);
+               LOGD("  caps: %s", caps_str);
        }
 
-       if (stype & GST_STREAM_TYPE_VIDEO) {
-               LOGW("VIDEO type 0x%X", stype);
-               if (type != MM_PLAYER_TRACK_TYPE_MAX) {
-                       LOGE("Multi Stream 0x%X", type);
-                       return -1;
+       switch (stype) {
+       case GST_STREAM_TYPE_AUDIO:
+       {
+               GstStructure *caps_structure = NULL;
+               gint samplerate = 0;
+               gint channels = 0;
+
+               type = MM_PLAYER_TRACK_TYPE_AUDIO;
+
+               if (caps) {
+                       caps_structure = gst_caps_get_structure(caps, 0);
+                       gst_structure_get_int(caps_structure, "rate", &samplerate);
+                       gst_structure_get_int(caps_structure, "channels", &channels);
+
+                       if (channels > 0 && samplerate == 0) {
+                               LOGW("Skip corrupted audio stream");
+                               goto EXIT;
+                       }
+
+                       if (g_strrstr(caps_str, "mobile-xmf"))
+                               mm_player_set_attribute((MMHandleType)player, NULL,
+                                       "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL);
                }
-               type = MM_PLAYER_TRACK_TYPE_VIDEO;
+               break;
        }
+       case GST_STREAM_TYPE_VIDEO:
+       {
+               GstStructure *caps_structure = NULL;
+               gint stype = 0;
+               gint width = 0;
 
-       if (stype & GST_STREAM_TYPE_TEXT) {
-               LOGW("TEXT type 0x%X", stype);
-               if (type != MM_PLAYER_TRACK_TYPE_MAX) {
-                       LOGE("Multi Stream 0x%X", type);
-                       return -1;
+               type = MM_PLAYER_TRACK_TYPE_VIDEO;
+
+               /* do not support multi track video */
+               if (player->track[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num >= 1)
+                       goto EXIT;
+
+               mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
+
+               /* don't make video because of not required */
+               if ((stype == MM_DISPLAY_SURFACE_NULL) &&
+                       (!player->set_mode.video_export)) {
+                       LOGD("no need video decoding, skip video stream");
+                       goto EXIT;
                }
+
+               if (caps) {
+                       caps_structure = gst_caps_get_structure(caps, 0);
+                       gst_structure_get_int(caps_structure, "width", &width);
+
+                       if (width != 0) {
+                               if (player->v_stream_caps) {
+                                       gst_caps_unref(player->v_stream_caps);
+                                       player->v_stream_caps = NULL;
+                               }
+
+                               player->v_stream_caps = gst_caps_copy(caps);
+                               MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
+                       }
+               }
+               break;
+       }
+       case GST_STREAM_TYPE_TEXT:
                type = MM_PLAYER_TRACK_TYPE_TEXT;
+               break;
+       default:
+               LOGW("Skip not supported stream type");
+               goto EXIT;
        }
 
        _mmplayer_track_update_stream(player, type, stream);
 
        if (player->track[type].active_track_index == (player->track[type].total_track_num - 1)) {
-               LOGD("select this stream, type : %d, idx : %d", type, player->track[type].active_track_index);
-               return 1;
+               LOGD("select this stream, active idx : %d", player->track[type].active_track_index);
+               if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
+                       _mmplayer_set_audio_attrs(player, caps);
+               ret = 1;
        }
 
-       return -1;
+EXIT:
+       g_free(caps_str);
+       gst_caps_unref(caps);
+
+       LOGD("ret %d", ret);
+       return ret;
 }
 
-void
+static gboolean
+__mmplayer_gst_decode_request_resource(GstElement * uridecodebin, GstStreamCollection * collection,
+    GstStream * stream, gpointer data)
+{
+       mmplayer_t *player = (mmplayer_t *)data;
+       GstStreamType stype = gst_stream_get_stream_type(stream);
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
+
+       LOGD("stream type %s", gst_stream_type_get_name(stype));
+
+       /* public does not support audio hw decoder at the moment */
+
+       if (player->hw_resource[MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER] != NULL) {
+               LOGW("video decoder resource is already acquired, skip it.");
+               return TRUE;
+       }
+
+       if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+               LOGE("failed to acquire video decoder resource");
+               return FALSE;
+       }
+       player->interrupted_by_resource = FALSE;
+       MMPLAYER_FLEAVE();
+       return TRUE;
+}
+
+static void
 __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
 {
        gchar *factory_name = NULL;
@@ -3022,10 +3118,23 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el
        }
 
        if (g_strrstr(factory_name, "parsebin")) {
+               int video_codec_type = 0;
+               int audio_codec_type = 0;
 
                g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
                g_object_set(G_OBJECT(element), "message-forward", TRUE, 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);
+
+               /* CAUTION: if there is hw decoder, the rank value has to be higher than sw decoder
+                  and codec default type in ini has to be hw.
+                */
+               if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+                       g_object_set(G_OBJECT(child), "force-sw-decoder-for-video", TRUE, NULL);
+               if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+                       g_object_set(G_OBJECT(child), "force-sw-decoder-for-audio", TRUE, NULL);
+
                mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].id = MMPLAYER_M_AUTOPLUG_PARSEBIN;
                mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].gst = element;
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
@@ -3034,13 +3143,12 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
                        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(element),
-                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort", G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
-
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
                        MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select", G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
 
+               _mmplayer_add_signal_connection(player, G_OBJECT(child),
+                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "request-resource", G_CALLBACK(__mmplayer_gst_decode_request_resource), (gpointer)player);
+
        } else {
                _mmplayer_gst_element_added((GstElement *)child, element, data);
        }
index e41a496..575f839 100644 (file)
@@ -144,7 +144,6 @@ static int          __mmplayer_gst_create_text_sink_bin(mmplayer_t *player);
 static void            __mmplayer_gst_create_sinkbin(GstElement *decodebin, GstPad *pad, gpointer data);
 static gboolean __mmplayer_is_midi_type(gchar *str_caps);
 static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
-static void            __mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps);
 
 static gboolean        __mmplayer_update_subtitle(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data);
 static void            __mmplayer_release_misc(mmplayer_t *player);
@@ -551,7 +550,7 @@ ALREADY_GOING:
        return MM_ERROR_PLAYER_NO_OP;
 }
 
-static int __mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type)
+int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type)
 {
        int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
        mm_resource_manager_res_type_e rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
@@ -1672,7 +1671,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
                        LOGD("display_surface_type (%d)", surface_type);
 
                        if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) &&
-                               (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
+                               (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
                                LOGE("failed to acquire video overlay resource");
                                goto ERROR;
                        }
@@ -2072,7 +2071,7 @@ _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
                        goto ERROR;
                }
        } else {
-               if (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
+               if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
                        LOGE("failed to acquire video overlay resource");
                        goto ERROR;
                }
@@ -5856,8 +5855,8 @@ __mmplayer_is_only_mp3_type(gchar *str_caps)
        return FALSE;
 }
 
-static void
-__mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
+void
+_mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
 {
        GstStructure *caps_structure = NULL;
        gint samplerate = 0;
@@ -6998,7 +6997,7 @@ __mmplayer_can_build_audio_offload_path(mmplayer_t *player)
        }
        gst_object_unref(factory);
 
-       if (__mmplayer_acquire_hw_resource(player,
+       if (_mmplayer_acquire_hw_resource(player,
                        MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD) != MM_ERROR_NONE) {
                LOGE("failed to acquire audio offload decoder resource");
                goto DONE;
@@ -7048,7 +7047,7 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps
 
                /* set stream information */
                if (!player->audiodec_linked)
-                       __mmplayer_set_audio_attrs(player, caps);
+                       _mmplayer_set_audio_attrs(player, caps);
 
                /* update codec info */
                player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
@@ -7067,7 +7066,7 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps
                                goto DONE;
                        }
 
-                       if (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+                       if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
                                LOGE("failed to acquire video decoder resource");
                                ret = GST_AUTOPLUG_SELECT_SKIP;
                                goto DONE;
@@ -7453,6 +7452,16 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
                gchar *selected = NULL;
                selected = g_strdup(GST_ELEMENT_NAME(element));
                player->audio_decoders = g_list_append(player->audio_decoders, selected);
+
+               /* update codec info */
+               player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+               player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+               player->audiodec_linked = 1;
+       } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
+               /* update codec info */
+               player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
+               player->can_support_codec |= FOUND_PLUGIN_VIDEO;
+               player->videodec_linked = 1;
        }
 
        if (g_strrstr(klass, "Demuxer/Adaptive")) {
@@ -8185,6 +8194,7 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind
        GstStream *stream = NULL;
        GList *streams = NULL;
        GstEvent *ev = NULL;
+       GstCaps *caps = NULL;
 
        LOGD("Switching Streams... type: %d, index: %d", type, index);
 
@@ -8197,6 +8207,14 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind
                        stream = g_ptr_array_index(player->track[i].streams, active_idx);
                        streams = g_list_append (streams, (gchar *)gst_stream_get_stream_id(stream));
                        LOGD("Selecting %d type stream : %s\n", i, gst_stream_get_stream_id(stream));
+
+                       if (i == MM_PLAYER_TRACK_TYPE_AUDIO) {
+                               caps = gst_stream_get_caps(stream);
+                               if (caps) {
+                                       _mmplayer_set_audio_attrs(player, caps);
+                                       gst_caps_unref(caps);
+                               }
+                       }
                }
        }
 
@@ -8283,7 +8301,10 @@ __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, i
                gst_object_unref(sinkpad);
 
        if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
-               __mmplayer_set_audio_attrs(player, caps);
+               _mmplayer_set_audio_attrs(player, caps);
+
+       if (caps)
+               gst_caps_unref(caps);
 
 EXIT:
        MMPLAYER_FREEIF(change_pad_name);