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);
MMPLAYER_INI_GET_STRING(dict, ini->gst_param[0], "general:gstparam1", DEFAULT_GST_PARAM);
__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);
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);
gchar **walk = NULL;
gint i = 0;
gchar *strtmp = NULL;
+ gchar (*ini_keyword)[PLAYER_INI_MAX_STRLEN] = {NULL, };
if (!str)
return;
/* trimming. it works inplace */
g_strstrip(strtmp);
-
/* split */
list = g_strsplit(strtmp, ",", 10);
/* 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);
}
#include <sys/time.h>
#include <stdlib.h>
#include <dlog.h>
+#include <gio/gio.h>
#include <mm_error.h>
#include <mm_attrs.h>
+#include <mm_sound.h>
#include "mm_player_priv.h"
#include "mm_player_ini.h"
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);
}
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;
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();
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;
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;
/* 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;