[0.6.172] add audio offload path 13/201313/3 accepted/tizen/unified/20190313.151523 submit/tizen/20190313.054921
authorEunhye Choi <eunhae1.choi@samsung.com>
Tue, 12 Mar 2019 09:21:44 +0000 (18:21 +0900)
committerEunhye Choi <eunhae1.choi@samsung.com>
Tue, 12 Mar 2019 10:59:09 +0000 (19:59 +0900)
Change-Id: Ia0323fe14818a050b6e08fb602c6ffc612f709ce

packaging/libmm-player.spec
src/include/mm_player.h
src/include/mm_player_ini.h
src/include/mm_player_priv.h
src/mm_player_attrs.c
src/mm_player_ini.c
src/mm_player_priv.c

index f81460e..e80c2cc 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-player
 Summary:    Multimedia Framework Player Library
-Version:    0.6.171
+Version:    0.6.172
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 2e0b8a6..e16c579 100644 (file)
  * rebuffer ms (int)
  */
 #define MM_PLAYER_REBUFFER_MS               "rebuffer_ms"
+/**
+ * MM_PLAYER_AUDIO_OFFLOAD (int)
+ */
+#define MM_PLAYER_AUDIO_OFFLOAD             "audio_offload"
 
 #define BUFFER_MAX_PLANE_NUM (4)
 
index 3123828..1c682a7 100644 (file)
@@ -70,6 +70,7 @@ typedef struct __mm_player_ini {
        gchar audiocodec_element_sw[PLAYER_INI_MAX_ELEMENT][PLAYER_INI_MAX_STRLEN];
        gchar audioresampler_element[PLAYER_INI_MAX_STRLEN];
        gchar audiosink_element[PLAYER_INI_MAX_STRLEN];
+       gchar audio_offload_sink_element[PLAYER_INI_MAX_STRLEN];
        gboolean skip_rescan;
        gboolean generate_dot;
        gboolean use_system_clock;
@@ -159,6 +160,7 @@ typedef struct __mm_player_ini {
 #define DEFAULT_PCM_BUFFER_SIZE                           51200 /* bytes */
 #define DEFAULT_NUM_OF_VIDEO_BO                           10
 #define DEFAULT_TIMEOUT_OF_VIDEO_BO                       10 /* sec */
+#define DEFAULT_AUDIO_OFFLOAD_SINK                        ""
 
 /* http streaming */
 #define DEFAULT_HTTPSRC                                   "souphttpsrc"
index c0b05ee..35d8f4c 100644 (file)
@@ -395,7 +395,6 @@ typedef struct {
 
 typedef struct {
        int uri_type;
-       int     play_mode;
        MMPlayerInputBuffer input_mem;
        char uri[MM_MAX_URL_LEN];
        char urgent[MM_MAX_FILENAME_LEN];
@@ -795,6 +794,9 @@ typedef struct {
 
        /* Video ROI area scale value */
        MMPlayerVideoROI video_roi;
+
+       /* build audio offload */
+       gboolean build_audio_offload;
 } mm_player_t;
 
 typedef struct {
index 42dfd2b..e8a1fea 100644 (file)
@@ -736,6 +736,15 @@ _mmplayer_construct_attribute(MMHandleType handle)
                        MIN_BUFFERING_TIME,
                        MMPLAYER_MAX_INT
                },
+               {
+                       "audio_offload",        /* MM_PLAYER_AUDIO_OFFLOAD */
+                       MM_ATTRS_TYPE_INT,
+                       MM_ATTRS_FLAG_RW,
+                       (void *)FALSE,
+                       MM_ATTRS_VALID_TYPE_INT_RANGE,
+                       FALSE,
+                       TRUE
+               },
        };
 
        num_of_attrs = ARRAY_SIZE(player_attrs);
index 89d9389..d8f022a 100644 (file)
@@ -156,6 +156,7 @@ mm_player_ini_load(mm_player_ini_t *ini)
                MMPLAYER_INI_GET_STRING(dict, ini->audioresampler_element, "general:audio resampler element", DEFAULT_AUDIORESAMPLER);
                MMPLAYER_INI_GET_STRING(dict, ini->audiocodec_element_hw, "general:audio codec element hw", DEFAULT_CODEC_HW);
                MMPLAYER_INI_GET_STRING(dict, ini->audiosink_element, "general:audiosink element", DEFAULT_AUDIOSINK);
+               MMPLAYER_INI_GET_STRING(dict, ini->audio_offload_sink_element, "general:audio offload sink element", DEFAULT_AUDIO_OFFLOAD_SINK);
 
                MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_overlay, "general:videosink element overlay", DEFAULT_VIDEOSINK_OVERLAY);
                MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_fake, "general:videosink element fake", DEFAULT_VIDEOSINK_FAKE);
@@ -213,6 +214,7 @@ mm_player_ini_load(mm_player_ini_t *ini)
 
                strncpy(ini->audioresampler_element, DEFAULT_AUDIORESAMPLER, PLAYER_INI_MAX_STRLEN - 1);
                strncpy(ini->audiosink_element, DEFAULT_AUDIOSINK, PLAYER_INI_MAX_STRLEN - 1);
+               strncpy(ini->audio_offload_sink_element, DEFAULT_AUDIO_OFFLOAD_SINK, PLAYER_INI_MAX_STRLEN - 1);
                strncpy(ini->audiocodec_element_hw, DEFAULT_CODEC_HW, PLAYER_INI_MAX_STRLEN - 1);
                strncpy(ini->videocodec_element_hw, DEFAULT_CODEC_HW, PLAYER_INI_MAX_STRLEN - 1);
                strncpy(ini->videoconverter_element, DEFAULT_VIDEO_CONVERTER, PLAYER_INI_MAX_STRLEN - 1);
@@ -258,6 +260,7 @@ mm_player_ini_load(mm_player_ini_t *ini)
                LOGD("audio codec element(sw%d) %s", idx, ini->audiocodec_element_sw[idx]);
        LOGD("audio resampler element : %s", ini->audioresampler_element);
        LOGD("audiosink element : %s", ini->audiosink_element);
+       LOGD("audio offload sink element : %s", ini->audio_offload_sink_element);
        LOGD("generate dot : %d", ini->generate_dot);
        LOGD("use system clock(video only) : %d", ini->use_system_clock);
        LOGD("live state change timeout(sec) : %d", ini->live_state_change_timeout);
@@ -461,7 +464,7 @@ __get_element_list(mm_player_ini_t *ini, gchar *str, int keyword_type)
 
        if (!list) {
                MMPLAYER_FREEIF(strtmp);
-       return;
+               return;
        }
 
        /* copy list */
index 21cf032..72b4c9c 100644 (file)
 /*---------------------------------------------------------------------------
 |    LOCAL DATA TYPE DEFINITIONS:                                                                                      |
 ---------------------------------------------------------------------------*/
+/* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
+ We are defining our own and will be removed when it actually exposed */
+typedef enum {
+       GST_AUTOPLUG_SELECT_TRY,
+       GST_AUTOPLUG_SELECT_EXPOSE,
+       GST_AUTOPLUG_SELECT_SKIP
+} GstAutoplugSelectResult;
 
 /*---------------------------------------------------------------------------
 |    GLOBAL VARIABLE DEFINITIONS:                                                                                      |
@@ -1120,14 +1127,16 @@ __mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
                gint samplerate = 0;
                gint channels = 0;
 
-               gst_structure_get_int(str, "rate", &samplerate);
-               gst_structure_get_int(str, "channels", &channels);
-
-               if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
+               if (MMPLAYER_IS_MS_BUFF_SRC(player) || player->build_audio_offload) {
+                       if (player->build_audio_offload)
+                               player->no_more_pad = TRUE; /* remove state holder */
                        __mmplayer_gst_create_sinkbin(elem, pad, player);
                        goto DONE;
                }
 
+               gst_structure_get_int(str, "rate", &samplerate);
+               gst_structure_get_int(str, "channels", &channels);
+
                if ((channels > 0 && samplerate == 0)) { /* exclude audio decoding */
                        __mmplayer_gst_make_fakesink(player, pad, name);
                        goto DONE;
@@ -1272,7 +1281,7 @@ __mmplayer_create_audio_sink_path(mm_player_t *player, GstElement *audio_selecto
        MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
 
        if (!audio_selector) {
-               LOGD("there is no audio track");
+               LOGD("there is no audio track, num_dynamic_pad %d", player->num_dynamic_pad);
 
                /* in case the source is changed, output can be changed. */
                if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
@@ -1389,6 +1398,12 @@ __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
        audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
        text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
 
+       if (!video_selector && !audio_selector && !text_selector) {
+               LOGW("there is no selector");
+               player->no_more_pad = TRUE;
+               goto EXIT;
+       }
+
        /* create video path followed by video-select */
        if (video_selector && !audio_selector && !text_selector)
                player->no_more_pad = TRUE;
@@ -2569,6 +2584,14 @@ __mmplayer_gst_fill_audio_bucket(mm_player_t *player, GList **bucket)
        audiobin = player->pipeline->audiobin;
        attrs = MMPLAYER_GET_ATTRS(player);
 
+       if (player->build_audio_offload) { /* skip all the audio filters */
+               LOGD("create audio offload sink : %s", player->ini.audio_offload_sink_element);
+               MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audio_offload_sink_element, "audiosink", TRUE, player);
+               g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", TRUE, NULL);
+               __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
+               goto DONE;
+       }
+
        /* converter */
        MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
 
@@ -2715,6 +2738,7 @@ __mmplayer_gst_fill_audio_bucket(mm_player_t *player, GList **bucket)
                __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
        }
 
+DONE:
        *bucket = element_bucket;
 
        MMPLAYER_FLEAVE();
@@ -6762,14 +6786,60 @@ __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad *pad,
        return ret;
 }
 
-static int
+static gboolean
+__mmplayer_check_offload_path(mm_player_t *player)
+{
+       gboolean ret = FALSE;
+       GstElementFactory *factory = NULL;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_VAL_IF_FAIL(player && player->attrs, FALSE);
+
+       if (strcmp(player->ini.audio_offload_sink_element, "")) {
+               /* FIXME : 1. need to consider the current audio output path and
+                       player have to know whether it support offload or not.
+                       2. could be added new condition about content length */
+               LOGD("current stream : %s, sink: %s", player->type, player->ini.audio_offload_sink_element);
+               if (!__mmplayer_is_only_mp3_type(player->type))
+                       goto DONE;
+
+               factory = gst_element_factory_find(player->ini.audio_offload_sink_element);
+               if (!factory)
+                       goto DONE;
+
+               LOGD("can setup the audio offload path");
+               gst_object_unref(factory);
+               ret = TRUE;
+       }
+
+DONE:
+       MMPLAYER_FLEAVE();
+       return ret;
+}
+
+static GstAutoplugSelectResult
 __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *caps, char *factory_name)
 {
-       int ret = MM_ERROR_NONE;
+       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"))) {
+               mm_attrs_get_int_by_name(player->attrs, "audio_offload", &audio_offload); /* user setting */
+
+               if (audio_offload && __mmplayer_check_offload_path(player)) {
+                       LOGD("expose audio path to build offload path");
+                       player->build_audio_offload = TRUE;
+                       /* update codec info */
+                       player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+                       player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+                       player->audiodec_linked = 1;
+
+                       ret = GST_AUTOPLUG_SELECT_EXPOSE;
+                       goto DONE;
+               }
+
                mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
 
                LOGD("audio codec type: %d", codec_type);
@@ -6778,7 +6848,7 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap
                        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 = MM_ERROR_PLAYER_INTERNAL;
+                                       ret = GST_AUTOPLUG_SELECT_SKIP;
                                        goto DONE;
                                }
                        }
@@ -6787,7 +6857,7 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap
                        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 = MM_ERROR_PLAYER_INTERNAL;
+                               ret = GST_AUTOPLUG_SELECT_SKIP;
                                goto DONE;
                        }
                }
@@ -6811,7 +6881,7 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap
                        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 = MM_ERROR_PLAYER_INTERNAL;
+                                       ret = GST_AUTOPLUG_SELECT_SKIP;
                                        goto DONE;
                                }
                        }
@@ -6819,7 +6889,7 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap
                        /* 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 = MM_ERROR_PLAYER_INTERNAL;
+                               ret = GST_AUTOPLUG_SELECT_SKIP;
                                goto DONE;
                        }
                }
@@ -6835,12 +6905,12 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap
                                                &player->video_decoder_resource)
                                        != MM_RESOURCE_MANAGER_ERROR_NONE) {
                                        LOGE("could not mark video_decoder resource for acquire");
-                                       ret = MM_ERROR_PLAYER_INTERNAL;
+                                       ret = GST_AUTOPLUG_SELECT_SKIP;
                                        goto DONE;
                                }
                        } else {
                                LOGW("video decoder resource is already acquired, skip it.");
-                               ret = MM_ERROR_PLAYER_INTERNAL;
+                               ret = GST_AUTOPLUG_SELECT_SKIP;
                                goto DONE;
                        }
 
@@ -6849,7 +6919,7 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap
                        if (mm_resource_manager_commit(player->resource_manager)
                                        != MM_RESOURCE_MANAGER_ERROR_NONE) {
                                LOGE("could not acquire resources for video decoding");
-                               ret = MM_ERROR_PLAYER_INTERNAL;
+                               ret = GST_AUTOPLUG_SELECT_SKIP;
                                goto DONE;
                        }
                }
@@ -6868,14 +6938,6 @@ gint
 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad *pad,
        GstCaps *caps, GstElementFactory *factory, gpointer data)
 {
-       /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
-        We are defining our own and will be removed when it actually exposed */
-       typedef enum {
-               GST_AUTOPLUG_SELECT_TRY,
-               GST_AUTOPLUG_SELECT_EXPOSE,
-               GST_AUTOPLUG_SELECT_SKIP
-       } GstAutoplugSelectResult;
-
        GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
        mm_player_t *player = (mm_player_t *)data;
 
@@ -6989,9 +7051,9 @@ __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad *pad,
        }
 
        if (g_strrstr(klass, "Codec/Decoder")) {
-               if (__mmplayer_check_codec_info(player, klass, caps, factory_name) != MM_ERROR_NONE) {
-                       LOGD("skipping %s codec", factory_name);
-                       result = GST_AUTOPLUG_SELECT_SKIP;
+               result = __mmplayer_check_codec_info(player, klass, caps, factory_name);
+               if (result != GST_AUTOPLUG_SELECT_TRY) {
+                       LOGW("skip add decoder");
                        goto DONE;
                }
        }