From: Eunhye Choi Date: Mon, 13 Apr 2020 07:49:27 +0000 (+0900) Subject: support playback with sw codec X-Git-Tag: accepted/tizen/unified/20200415.121431~1^2~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git;a=commitdiff_plain;h=781c17b6d81658a45600a6e8a017fff1ac0cc481 support playback with sw codec - 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 --- diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index a440e6c..1f321f1 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -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 } diff --git a/src/mm_player_gst.c b/src/mm_player_gst.c index c864487..bb16882 100644 --- a/src/mm_player_gst.c +++ b/src/mm_player_gst.c @@ -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); } diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index e41a496..575f839 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -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);