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);
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);
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);
if (!list) {
MMPLAYER_FREEIF(strtmp);
- return;
+ return;
}
/* copy list */
/*---------------------------------------------------------------------------
| 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: |
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;
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)) {
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;
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);
__mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
}
+DONE:
*bucket = element_bucket;
MMPLAYER_FLEAVE();
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);
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;
}
}
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;
}
}
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;
}
}
/* 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;
}
}
&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;
}
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;
}
}
__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;
}
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;
}
}