From 5c933d3118cbf20f99d33047f705c2776b1c7608 Mon Sep 17 00:00:00 2001 From: Eunhye Choi Date: Wed, 27 Mar 2019 20:51:15 +0900 Subject: [PATCH] [0.6.177] check audio out for offload setup - get current audio device type and check whether it can support offload or not based on the ini - add device connected cb to monitor the changes of audio device Change-Id: I83349d6310dbe327250c58c7331b88343f3731be --- packaging/libmm-player.spec | 2 +- src/include/mm_player_ini.h | 9 +- src/include/mm_player_priv.h | 4 +- src/mm_player_ini.c | 87 +++++++----------- src/mm_player_priv.c | 172 +++++++++++++++++++++++++++++++---- 5 files changed, 194 insertions(+), 80 deletions(-) diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 159c16e..ab63c49 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.176 +Version: 0.6.177 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_player_ini.h b/src/include/mm_player_ini.h index 1c682a7..193a480 100644 --- a/src/include/mm_player_ini.h +++ b/src/include/mm_player_ini.h @@ -52,11 +52,12 @@ * of each string item. */ enum keyword_type { - KEYWORD_EXCLUDE, // for element exclude keyworld - KEYWORD_DUMP, // for dump element keyworld + KEYWORD_EXCLUDE, // for element exclude keyword + KEYWORD_DUMP, // for dump element keyword KEYWORD_UNSUPPORTED_CODEC, // for un-supported codec KEYWORD_A_SW_CODEC, // for audio sw codec - KEYWORD_V_SW_CODEC // for video sw codec + KEYWORD_V_SW_CODEC, // for video sw codec + KEYWORD_A_OFFLOAD, // for audio device type which can support offload }; typedef struct __mm_player_ini { @@ -71,6 +72,7 @@ typedef struct __mm_player_ini { gchar audioresampler_element[PLAYER_INI_MAX_STRLEN]; gchar audiosink_element[PLAYER_INI_MAX_STRLEN]; gchar audio_offload_sink_element[PLAYER_INI_MAX_STRLEN]; + gchar audio_offload_device_type[PLAYER_INI_MAX_ELEMENT][PLAYER_INI_MAX_STRLEN]; gboolean skip_rescan; gboolean generate_dot; gboolean use_system_clock; @@ -148,6 +150,7 @@ typedef struct __mm_player_ini { #define DEFAULT_AUDIOSINK "pulsesink" #define DEFAULT_CODEC_HW "" #define DEFAULT_CODEC_SW "" +#define DEFAULT_A_OFFLOAD_DEVICE_TYPE "" #define DEFAULT_GST_PARAM "" #define DEFAULT_EXCLUDE_KEYWORD "" #define DEFAULT_UNSUPPORTED_CODEC_KEYWORD "" diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 216357a..726f776 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -742,9 +742,6 @@ typedef struct { GCond subtitle_info_cond; GMutex subtitle_info_mutex; - /* To store the current multiwindow status */ - gboolean last_multiwin_status; - /* To store the current running audio pad index of demuxer */ gint demux_pad_index; @@ -798,6 +795,7 @@ typedef struct { /* build audio offload */ gboolean build_audio_offload; + guint audio_device_cb_id; } mm_player_t; typedef struct { diff --git a/src/mm_player_ini.c b/src/mm_player_ini.c index d8f022a..dca9e1e 100644 --- a/src/mm_player_ini.c +++ b/src/mm_player_ini.c @@ -172,6 +172,9 @@ mm_player_ini_load(mm_player_ini_t *ini) __get_element_list(ini, iniparser_getstring(dict, "general:element exclude keyword", DEFAULT_EXCLUDE_KEYWORD), KEYWORD_EXCLUDE); + __get_element_list(ini, + iniparser_getstring(dict, "general:audio offload device type", DEFAULT_A_OFFLOAD_DEVICE_TYPE), KEYWORD_A_OFFLOAD); + __get_element_list(ini, iniparser_getstring(dict, "general:unsupported codec keyword", DEFAULT_UNSUPPORTED_CODEC_KEYWORD), KEYWORD_UNSUPPORTED_CODEC); @@ -221,6 +224,7 @@ mm_player_ini_load(mm_player_ini_t *ini) __get_element_list(ini, DEFAULT_CODEC_SW, KEYWORD_A_SW_CODEC); __get_element_list(ini, DEFAULT_CODEC_SW, KEYWORD_V_SW_CODEC); + __get_element_list(ini, DEFAULT_A_OFFLOAD_DEVICE_TYPE, KEYWORD_A_OFFLOAD); __get_element_list(ini, DEFAULT_EXCLUDE_KEYWORD, KEYWORD_EXCLUDE); __get_element_list(ini, DEFAULT_UNSUPPORTED_CODEC_KEYWORD, KEYWORD_UNSUPPORTED_CODEC); @@ -261,6 +265,8 @@ mm_player_ini_load(mm_player_ini_t *ini) 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); + for (idx = 0; ini->audio_offload_device_type[idx][0] != '\0'; idx++) + LOGD("audio_offload_device_type [%d] : %s", idx, ini->audio_offload_device_type[idx]); 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); @@ -446,6 +452,7 @@ __get_element_list(mm_player_ini_t *ini, gchar *str, int keyword_type) gchar **walk = NULL; gint i = 0; gchar *strtmp = NULL; + gchar (*ini_keyword)[PLAYER_INI_MAX_STRLEN] = {NULL, }; if (!str) return; @@ -458,7 +465,6 @@ __get_element_list(mm_player_ini_t *ini, gchar *str, int keyword_type) /* trimming. it works inplace */ g_strstrip(strtmp); - /* split */ list = g_strsplit(strtmp, ",", 10); @@ -470,72 +476,45 @@ __get_element_list(mm_player_ini_t *ini, gchar *str, int keyword_type) /* copy list */ switch (keyword_type) { case KEYWORD_EXCLUDE: - { - for (walk = list; *walk; walk++) { - strncpy(ini->exclude_element_keyword[i], *walk, (PLAYER_INI_MAX_STRLEN - 1)); - g_strstrip(ini->exclude_element_keyword[i]); - ini->exclude_element_keyword[i][PLAYER_INI_MAX_STRLEN -1] = '\0'; - i++; - } - /* mark last item to NULL */ - ini->exclude_element_keyword[i][0] = '\0'; - + ini_keyword = ini->exclude_element_keyword; break; - } case KEYWORD_DUMP: - { - for (walk = list; *walk; walk++) { - strncpy(ini->dump_element_keyword[i], *walk, (PLAYER_INI_MAX_STRLEN - 1)); - g_strstrip(ini->dump_element_keyword[i]); - ini->dump_element_keyword[i][PLAYER_INI_MAX_STRLEN -1] = '\0'; - i++; - } - /* mark last item to NULL */ - ini->dump_element_keyword[i][0] = '\0'; - + ini_keyword = ini->dump_element_keyword; break; - } case KEYWORD_UNSUPPORTED_CODEC: - { - for (walk = list; *walk; walk++) { - strncpy(ini->unsupported_codec_keyword[i], *walk, (PLAYER_INI_MAX_STRLEN - 1)); - g_strstrip(ini->unsupported_codec_keyword[i]); - ini->unsupported_codec_keyword[i][PLAYER_INI_MAX_STRLEN -1] = '\0'; - i++; - } - /* mark last item to NULL */ - ini->unsupported_codec_keyword[i][0] = '\0'; + ini_keyword = ini->unsupported_codec_keyword; break; - } case KEYWORD_V_SW_CODEC: - { - for (walk = list; *walk; walk++) { - strncpy(ini->videocodec_element_sw[i], *walk, (PLAYER_INI_MAX_STRLEN - 1)); - g_strstrip(ini->videocodec_element_sw[i]); - ini->videocodec_element_sw[i][PLAYER_INI_MAX_STRLEN -1] = '\0'; - i++; - } - /* mark last item to NULL */ - ini->videocodec_element_sw[i][0] = '\0'; + ini_keyword = ini->videocodec_element_sw; break; - } case KEYWORD_A_SW_CODEC: - { - for (walk = list; *walk; walk++) { - strncpy(ini->audiocodec_element_sw[i], *walk, (PLAYER_INI_MAX_STRLEN - 1)); - g_strstrip(ini->audiocodec_element_sw[i]); - ini->audiocodec_element_sw[i][PLAYER_INI_MAX_STRLEN -1] = '\0'; - i++; - } - /* mark last item to NULL */ - ini->audiocodec_element_sw[i][0] = '\0'; + ini_keyword = ini->audiocodec_element_sw; + break; + case KEYWORD_A_OFFLOAD: + ini_keyword = ini->audio_offload_device_type; break; - } - default: + goto EXIT; break; } + for (walk = list; *walk && ini_keyword[i]; walk++) { + strncpy(ini_keyword[i], *walk, (PLAYER_INI_MAX_STRLEN - 1)); + g_strstrip(ini_keyword[i]); + ini_keyword[i][PLAYER_INI_MAX_STRLEN -1] = '\0'; + i++; + } + + /* mark last item to NULL */ + if (ini_keyword[i]) { + ini_keyword[i][0] = '\0'; + } else { + LOGE("too many keyword exist in list (%d)", i); + if (i > 0) + ini_keyword[i-1][0] = '\0'; + } + +EXIT: g_strfreev(list); MMPLAYER_FREEIF(strtmp); } diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index c241425..75b3e1a 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -35,9 +35,11 @@ #include #include #include +#include #include #include +#include #include "mm_player_priv.h" #include "mm_player_ini.h" @@ -4858,7 +4860,6 @@ _mmplayer_realize(MMHandleType hplayer) player->demux_pad_index = 0; player->subtitle_language_list = NULL; player->is_subtitle_force_drop = FALSE; - player->last_multiwin_status = FALSE; __mmplayer_track_initialize(player); __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX); @@ -6826,7 +6827,124 @@ __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, } static gboolean -__mmplayer_check_offload_path(mm_player_t *player) +__mmplayer_is_offload_supportable(mm_player_t *player) +{ + gboolean ret = TRUE; + GDBusConnection *conn = NULL; + GError *err = NULL; + GVariant *result = NULL; + const gchar *dbus_device_type = NULL; + const gchar *dbus_ret = NULL; + gint idx = 0; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!conn || err) { + LOGE("failed g_bus_get_sync() (%s)", err ? err->message : NULL); + g_error_free(err); + ret = FALSE; + goto DONE; + } + + result = g_dbus_connection_call_sync(conn, + "org.pulseaudio.Server", + "/org/pulseaudio/StreamManager", + "org.pulseaudio.StreamManager", + "GetCurrentMediaRoutingPath", + g_variant_new("(s)", "out"), + G_VARIANT_TYPE("(ss)"), + G_DBUS_CALL_FLAGS_NONE, + 2000, + NULL, + &err); + if (!result || err) { + LOGE("failed g_dbus_connection_call_sync() (%s)", err ? err->message : NULL); + g_error_free(err); + ret = FALSE; + goto DONE; + } + + /* device type is listed in stream-map.json at mmfw-sysconf */ + g_variant_get(result, "(&s&s)", &dbus_device_type, &dbus_ret); + + LOGI("g_dbus_connection_call_sync() success (%s, %s)", dbus_device_type, dbus_ret); + if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) { + ret = FALSE; + goto DONE; + } + + /* the device type is listed in ini file among audio-jack, bt-a2dp, usb-audio, builtin-speaker */ + for (idx = 0; player->ini.audio_offload_device_type[idx][0] != '\0'; idx++) { + if (strstr(dbus_device_type, player->ini.audio_offload_device_type[idx])) { + LOGD("audio offload is supportable"); + ret = TRUE; + goto DONE; + } + } + + LOGD("audio offload is not supportable"); + ret = FALSE; + +DONE: + g_variant_unref(result); + g_object_unref(conn); + + return ret; +} + +void __mmplayer_audio_device_connected_cb(MMSoundDevice_t device_h, bool is_connected, void *user_data) +{ + mm_player_t *player = (mm_player_t *)user_data; + mm_sound_device_type_e dev_type = MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER; + gboolean is_supportable = FALSE; + + if (mm_sound_get_device_type(device_h, &dev_type) != MM_ERROR_NONE) + LOGW("failed to get device type"); + else + LOGD("dev type (%d), connected (%d)", dev_type, is_connected); + + if ((dev_type != MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP) && + (dev_type != MM_SOUND_DEVICE_TYPE_AUDIOJACK) && + (dev_type != MM_SOUND_DEVICE_TYPE_USB_AUDIO)) { + LOGD("ignore this dev connected info"); + return; + } + + is_supportable = __mmplayer_is_offload_supportable(player); + if (player->build_audio_offload == is_supportable) { + LOGD("keep current pipeline without re-building"); + return; + } + + /* FIXME: rebuild pipeline */ + LOGD("FIXME: re-build pipeline"); + + return; +} + +static gboolean +__mmplayer_add_audio_device_connected_cb(mm_player_t *player) +{ + unsigned int id = 0; + + if (player->audio_device_cb_id != 0) { + LOGW("audio device connected cb was already added (%u)", player->audio_device_cb_id); + return TRUE; + } + + if (mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG, + __mmplayer_audio_device_connected_cb, player, &id) == MM_ERROR_NONE) { + LOGD("added device connected cb (%u)", id); + player->audio_device_cb_id = id; + } else { + LOGW("failed to add device connected cb"); + return FALSE; + } + + return TRUE; +} + +static gboolean +__mmplayer_can_build_audio_offload_path(mm_player_t *player) { gboolean ret = FALSE; GstElementFactory *factory = NULL; @@ -6834,22 +6952,35 @@ __mmplayer_check_offload_path(mm_player_t *player) 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; + 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; + if (!strcmp(player->ini.audio_offload_sink_element, "")) { + LOGD("there is no audio offload sink"); + goto DONE; + } - LOGD("can setup the audio offload path"); - gst_object_unref(factory); - ret = TRUE; + if (player->ini.audio_offload_device_type[0][0] == '\0') { + LOGW("there is no audio device type to support offload"); + goto DONE; + } + + factory = gst_element_factory_find(player->ini.audio_offload_sink_element); + if (!factory) { + LOGW("there is no installed audio offload sink element"); + goto DONE; } + gst_object_unref(factory); + + if (!__mmplayer_add_audio_device_connected_cb(player)) + goto DONE; + + if (!__mmplayer_is_offload_supportable(player)) + goto DONE; + + LOGD("audio offload can be built"); + ret = TRUE; DONE: MMPLAYER_FLEAVE(); @@ -6865,10 +6996,10 @@ __mmplayer_check_codec_info(mm_player_t *player, const char *klass, GstCaps *cap 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 */ + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_OFFLOAD, &audio_offload); /* user requirement */ - if (audio_offload && __mmplayer_check_offload_path(player)) { - LOGD("expose audio path to build offload path"); + if (audio_offload && __mmplayer_can_build_audio_offload_path(player)) { + LOGD("expose audio path to build offload output path"); player->build_audio_offload = TRUE; /* update codec info */ player->not_supported_codec &= MISSING_PLUGIN_VIDEO; @@ -7337,7 +7468,6 @@ __mmplayer_release_misc(mm_player_t *player) player->is_subtitle_force_drop = FALSE; player->play_subtitle = FALSE; player->adjust_subtitle_pos = 0; - player->last_multiwin_status = FALSE; player->has_closed_caption = FALSE; player->set_mode.media_packet_video_stream = false; player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE; @@ -7345,6 +7475,10 @@ __mmplayer_release_misc(mm_player_t *player) /* recover mode */ player->set_mode.rich_audio = cur_mode; + if (mm_sound_remove_device_connected_callback(player->audio_device_cb_id) != MM_ERROR_NONE) + LOGW("failed to remove audio device_connected_callback"); + player->audio_device_cb_id = 0; + for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) { player->bitrate[i] = 0; player->maximum_bitrate[i] = 0; -- 2.34.1