#include "mm_player_priv.h"
#include "mm_player_ini.h"
-#include "mm_player_attrs.h"
#include "mm_player_capture.h"
#include "mm_player_utils.h"
#include "mm_player_tracks.h"
/* util */
static gboolean __mmplayer_verify_gapless_play_path(mmplayer_t *player);
-static void __mmplayer_check_pipeline(mmplayer_t *player);
+static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player);
static gboolean __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type);
static void __mmplayer_deactivate_old_path(mmplayer_t *player);
static int __mmplayer_gst_create_plain_text_elements(mmplayer_t *player);
MMPLAYER_FLEAVE();
}
+void _mmplayer_set_reconfigure_state(mmplayer_t *player, gboolean state)
+{
+ LOGI("set pipeline reconfigure state %d", state);
+ MMPLAYER_RECONFIGURE_LOCK(player);
+ player->gapless.reconfigure = state;
+ if (!state) /* wake up the waiting job */
+ MMPLAYER_RECONFIGURE_SIGNAL(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
+}
+
static gpointer
__mmplayer_gapless_play_thread(gpointer data)
{
LOGD("reconfigure pipeline for gapless play.");
if (player->gapless_play_thread_exit) {
- if (player->gapless.reconfigure) {
- player->gapless.reconfigure = false;
- MMPLAYER_PLAYBACK_UNLOCK(player);
- }
+ _mmplayer_set_reconfigure_state(player, FALSE);
LOGD("exiting gapless play thread");
break;
}
}
void
+_mmplayer_watcher_removed_notify(gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+ MMPLAYER_RETURN_IF_FAIL(player);
+
+ MMPLAYER_BUS_WATCHER_LOCK(player);
+ player->bus_watcher = 0;
+ MMPLAYER_BUS_WATCHER_SIGNAL(player);
+ MMPLAYER_BUS_WATCHER_UNLOCK(player);
+}
+
+void
+_mmplayer_bus_watcher_remove(MMHandleType hplayer)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ gint64 end_time = 0;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player);
+
+ /* disconnecting bus watch */
+ if (player->bus_watcher > 0) {
+ __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
+ MMPLAYER_BUS_WATCHER_LOCK(player);
+ end_time = g_get_monotonic_time () + 2 * G_TIME_SPAN_SECOND;
+ while (player->bus_watcher > 0)
+ MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time);
+ MMPLAYER_BUS_WATCHER_UNLOCK(player);
+
+ g_mutex_clear(&player->bus_watcher_mutex);
+ g_cond_clear(&player->bus_watcher_cond);
+ }
+
+ MMPLAYER_FLEAVE();
+}
+
+void
_mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
- /* disconnecting bus watch */
- if (player->bus_watcher)
- __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
- player->bus_watcher = 0;
-
/* destroy the gst bus msg thread */
if (player->bus_msg_thread) {
MMPLAYER_BUS_MSG_THREAD_LOCK(player);
const gchar *name = NULL;
GstPad *sinkpad = NULL;
gboolean first_track = FALSE;
- gboolean caps_ret = TRUE;
main_element_id_e elem_idx = MMPLAYER_M_NUM;
mmplayer_track_type_e stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
LOGD("pad-added signal handling");
/* get mimetype from caps */
- MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
- if (!caps_ret)
+ caps = gst_pad_get_current_caps(pad);
+ if (caps) {
+ str = gst_caps_get_structure(caps, 0);
+ if (str)
+ name = gst_structure_get_name(str);
+ }
+ if (!name)
goto ERROR;
MMPLAYER_LOG_GST_CAPS_TYPE(caps);
__mmplayer_create_text_sink_path(player, text_selector);
EXIT:
- if (player->gapless.reconfigure) {
- player->gapless.reconfigure = FALSE;
- MMPLAYER_PLAYBACK_UNLOCK(player);
- }
-
+ _mmplayer_set_reconfigure_state(player, FALSE);
MMPLAYER_FLEAVE();
}
LOGD("set video param : wl_surface_id %d", handle);
gst_video_overlay_set_wl_window_wl_surface_id(
GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- (guintptr)handle);
+ handle);
}
int
audio_stream.bitrate = a_buffer->bitrate;
audio_stream.channel = a_buffer->channel;
- audio_stream.depth = a_buffer->depth;
- audio_stream.is_little_endian = a_buffer->is_little_endian;
audio_stream.channel_mask = a_buffer->channel_mask;
audio_stream.data_size = a_buffer->data_size;
audio_stream.data = a_buffer->pcm_data;
const gchar *pcm_format = NULL;
gint channel = 0;
gint rate = 0;
- gint depth = 0;
- gint endianness = 0;
guint64 channel_mask = 0;
void *a_data = NULL;
gint a_size = 0;
pcm_format = gst_structure_get_string(structure, "format");
gst_structure_get_int(structure, "rate", &rate);
gst_structure_get_int(structure, "channels", &channel);
- gst_structure_get_int(structure, "depth", &depth);
- gst_structure_get_int(structure, "endianness", &endianness);
gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
gst_caps_unref(GST_CAPS(caps));
}
a_buffer->bitrate = rate;
a_buffer->channel = channel;
- a_buffer->depth = depth;
- a_buffer->is_little_endian = (endianness == 1234 ? true : false);
a_buffer->channel_mask = channel_mask;
a_buffer->data_size = a_size;
a_buffer->pcm_format = _mmplayer_convert_audio_pcm_str_to_media_format_mime(pcm_format);
switch (latency_mode) {
case AUDIO_LATENCY_MODE_LOW:
- latency = g_strndup("low", 3);
+ latency = g_strdup("low");
break;
case AUDIO_LATENCY_MODE_MID:
- latency = g_strndup("mid", 3);
+ latency = g_strdup("mid");
break;
case AUDIO_LATENCY_MODE_HIGH:
- latency = g_strndup("high", 4);
+ latency = g_strdup("high");
+ break;
+ default:
+ latency = g_strdup("mid");
break;
};
MMPLAYER_FLEAVE();
}
-void
+int
__mmplayer_gst_set_openalsink_property(mmplayer_t *player)
{
mmplayer_gst_element_t *audiobin = NULL;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
audiobin = player->pipeline->audiobin;
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
- sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
+ if (sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info)) {
+ LOGE("failed to create media stream info");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
if (player->video360_yaw_radians <= M_PI &&
}
MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
}
static int
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL);
}
- if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
+ if (g_strrstr(player->ini.audiosink_element, "pulsesink")) {
__mmplayer_gst_set_pulsesink_property(player);
- else if (g_strrstr(player->ini.audiosink_element, "openalsink"))
- __mmplayer_gst_set_openalsink_property(player);
+ } else if (g_strrstr(player->ini.audiosink_element, "openalsink")) {
+ if (__mmplayer_gst_set_openalsink_property(player) != MM_ERROR_NONE)
+ goto ERROR;
+ }
/* qos on */
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */
return MM_ERROR_PLAYER_INTERNAL;
}
- LOGD("surface type %d, videosink factory name is %s", surface_type, factory_name);
if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
- if (!use_tbm) {
- /* support shard memory with S/W codec on HawkP */
- if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- "use-tbm", use_tbm, NULL);
- }
+ if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
+ g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
+ "use-tbm", use_tbm, NULL);
}
if (_mmplayer_update_video_overlay_param(player, "update_all_param") != MM_ERROR_NONE)
return MM_ERROR_PLAYER_INTERNAL;
+
+ LOGI("videosink factory name is %s use-tbm : %d", factory_name, use_tbm);
+
} else {
g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
"sync", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
if (textbin[MMPLAYER_T_BIN].gst)
gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
- MMPLAYER_FREEIF(player->pipeline->textbin);
+ MMPLAYER_FREEIF(textbin);
player->pipeline->textbin = NULL;
MMPLAYER_FLEAVE();
}
player->pipeline = (mmplayer_pipeline_info_t *)g_malloc0(sizeof(mmplayer_pipeline_info_t));
- if (player->pipeline == NULL)
- goto INIT_ERROR;
/* create mainbin */
mainbin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_M_NUM);
return MM_ERROR_NONE;
INIT_ERROR:
+ _mmplayer_bus_watcher_remove(player);
__mmplayer_gst_destroy_pipeline(player);
return MM_ERROR_PLAYER_INTERNAL;
}
player->subtitle_language_list = NULL;
MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
+ MMPLAYER_RECONFIGURE_LOCK(player);
__mmplayer_reset_gapless_state(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
if (player->streamer) {
_mm_player_streaming_initialize(player->streamer, FALSE);
player->resource_manager))
LOGE("failed to deinitialize resource manager");
+ /* release miscellaneous information */
+ __mmplayer_release_misc(player);
+
/* release pipeline */
if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
LOGE("failed to destory pipeline");
__mmplayer_release_dump_list(player->dump_list);
- /* release miscellaneous information */
- __mmplayer_release_misc(player);
-
/* release miscellaneous information.
these info needs to be released after pipeline is destroyed. */
__mmplayer_release_misc_post(player);
/* release attributes */
_mmplayer_deconstruct_attribute(handle);
+ if (player->uri_info.uri_list) {
+ GList *uri_list = player->uri_info.uri_list;
+ for (; uri_list; uri_list = g_list_next(uri_list)) {
+ gchar *uri = uri_list->data;
+ MMPLAYER_FREEIF(uri);
+ }
+ g_list_free(player->uri_info.uri_list);
+ player->uri_info.uri_list = NULL;
+ }
+
/* release lock */
g_mutex_clear(&player->fsink_lock);
_mmplayer_realize(MMHandleType hplayer)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
+ int ret = MM_ERROR_NONE;
char *uri = NULL;
void *param = NULL;
MMHandleType attrs = 0;
- int ret = MM_ERROR_NONE;
-
+ int video_codec_type = 0;
+ int audio_codec_type = 0;
+ int default_codec_type = 0;
MMPLAYER_FENTER();
/* check player handle */
player->streamer->buffering_req.rebuffer_time);
}
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
+ if (!strcmp(player->ini.audiocodec_default_type, "hw"))
+ default_codec_type = MM_PLAYER_CODEC_TYPE_HW;
+ else
+ default_codec_type = MM_PLAYER_CODEC_TYPE_SW;
+
+ if (audio_codec_type != default_codec_type) {
+ LOGD("audio dec sorting is required");
+ player->need_audio_dec_sorting = TRUE;
+ }
+
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
+ if (video_codec_type != MM_PLAYER_CODEC_TYPE_DEFAULT) {
+ LOGD("video dec sorting is required");
+ player->need_video_dec_sorting = TRUE;
+ }
+
/* realize pipeline */
ret = __mmplayer_gst_realize(player);
if (ret != MM_ERROR_NONE)
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_CMD_UNLOCK(player);
+ _mmplayer_bus_watcher_remove(player);
/* destroy the gst bus msg thread which is created during realize.
this funct have to be called before getting cmd lock. */
_mmplayer_bus_msg_thread_destroy(player);
return MM_ERROR_NONE;
}
-static void
-__mmplayer_check_pipeline(mmplayer_t *player)
+static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player)
{
GstState element_state = GST_STATE_VOID_PENDING;
GstState element_pending_state = GST_STATE_VOID_PENDING;
- gint timeout = 0;
- int ret = MM_ERROR_NONE;
+ GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+ gint timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- if (!player->gapless.reconfigure)
- return;
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline);
- LOGW("pipeline is under construction.");
+ MMPLAYER_RECONFIGURE_LOCK(player);
+ if (!player->gapless.reconfigure) {
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
+ return;
+ }
- MMPLAYER_PLAYBACK_LOCK(player);
- MMPLAYER_PLAYBACK_UNLOCK(player);
+ LOGI("reconfigure is under process");
+ MMPLAYER_RECONFIGURE_WAIT(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
+ LOGI("reconfigure is completed.");
- timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
+ result = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+ &element_state, &element_pending_state, timeout * GST_SECOND);
+ if (result == GST_STATE_CHANGE_FAILURE)
+ LOGW("failed to get pipeline state in %d sec", timeout);
- /* wait for state transition */
- ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
- if (ret == GST_STATE_CHANGE_FAILURE)
- LOGE("failed to change pipeline state within %d sec", timeout);
+ return;
}
/* NOTE : it should be able to call 'stop' anytime*/
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
- /* check pipline building state */
- __mmplayer_check_pipeline(player);
+ /* need to wait till the rebuilding pipeline is completed */
+ __mmplayer_check_pipeline_reconfigure_state(player);
+ MMPLAYER_RECONFIGURE_LOCK(player);
__mmplayer_reset_gapless_state(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
/* NOTE : application should not wait for EOS after calling STOP */
_mmplayer_cancel_eos_timer(player);
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
- /* check pipline building state */
- __mmplayer_check_pipeline(player);
+ /* check pipline reconfigure state */
+ __mmplayer_check_pipeline_reconfigure_state(player);
switch (MMPLAYER_CURRENT_STATE(player)) {
case MM_PLAYER_STATE_READY:
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- /* check pipline building state */
- __mmplayer_check_pipeline(player);
+ /* check pipline reconfigure state */
+ __mmplayer_check_pipeline_reconfigure_state(player);
ret = _mmplayer_gst_set_position(player, position, FALSE);
_mmplayer_add_signal_connection(player, G_OBJECT(decodebin), 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(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
+ G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
+
/* This signal is emitted whenever decodebin finds a new stream. It is emitted
before looking for any elements that can handle that stream.*/
_mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
LOGD("[handle: %p] pipeline has completely constructed", player);
- if ((player->ini.async_start) &&
- (player->msg_posted == FALSE) &&
+ if ((player->msg_posted == FALSE) &&
(player->cmd >= MMPLAYER_COMMAND_START))
__mmplayer_handle_missed_plugin(player);
player->streamer = NULL;
}
- MMPLAYER_PLAYBACK_LOCK(player);
MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
-
MMPLAYER_FLEAVE();
return;
"content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL);
MMPLAYER_FREEIF(caps_str);
- } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
- MMMessageParamType msg_param;
- memset(&msg_param, 0, sizeof(MMMessageParamType));
- msg_param.code = MM_ERROR_NOT_SUPPORT_API;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
- LOGD("video file is not supported on this device");
- ret = FALSE;
} else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
LOGD("already video linked");
ret = FALSE;
static gboolean
__mmplayer_is_audio_offload_device_type(mmplayer_t *player)
{
- gboolean ret = TRUE;
+ gboolean ret = FALSE;
GDBusConnection *conn = NULL;
GError *err = NULL;
GVariant *result = NULL;
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);
+ LOGE("failed g_bus_get_sync() (%s)", (err ? err->message : "null"));
g_error_free(err);
- ret = FALSE;
goto DONE;
}
NULL,
&err);
if (!result || err) {
- LOGE("failed g_dbus_connection_call_sync() (%s)", err ? err->message : NULL);
+ LOGE("failed g_dbus_connection_call_sync() (%s)", (err ? err->message : "null"));
g_error_free(err);
- ret = FALSE;
goto DONE;
}
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;
+ if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
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++) {
}
LOGD("audio offload is not supportable");
- ret = FALSE;
DONE:
g_variant_unref(result);
- g_object_unref(conn);
+ if (conn)
+ g_object_unref(conn);
return ret;
}
__mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps, char *factory_name)
{
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"))) {
goto DONE;
}
- mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
-
- LOGD("audio codec type: %d", codec_type);
- if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
- /* sw codec will be skipped */
- 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 = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
- } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
- /* hw codec will be skipped */
- 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 = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
+ /* FIXME: If HW audio decoder is selected, related resource have to be acquired here.
+ And need to consider the multi-track audio content.
+ There is no HW audio decoder in public. */
/* set stream information */
if (!player->audiodec_linked)
} else if (g_strrstr(klass, "Codec/Decoder/Video")) {
- mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
-
- LOGD("video codec type: %d", codec_type);
- if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
- /* sw codec is skipped */
- 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 = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
- } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
- /* 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 = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
-
if ((strlen(player->ini.videocodec_element_hw) > 0) &&
(g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
return ret;
}
+GValueArray *
+_mmplayer_gst_decode_autoplug_sort(GstElement *bin,
+ GstPad *pad, GstCaps *caps, GValueArray *factories, gpointer data)
+{
+#define DEFAULT_IDX 0xFFFF
+#define MIN_FACTORY_NUM 2
+ mmplayer_t *player = (mmplayer_t *)data;
+ GValueArray *new_factories = NULL;
+ GValue val = { 0, };
+ GstElementFactory *factory = NULL;
+ const gchar *klass = NULL;
+ gchar *factory_name = NULL;
+ guint hw_dec_idx = DEFAULT_IDX;
+ guint first_sw_dec_idx = DEFAULT_IDX;
+ guint last_sw_dec_idx = DEFAULT_IDX;
+ guint new_pos = DEFAULT_IDX;
+ guint rm_pos = DEFAULT_IDX;
+ int audio_codec_type;
+ int video_codec_type;
+ mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+
+ if (factories->n_values < MIN_FACTORY_NUM)
+ return 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);
+
+#ifdef __DEBUG__
+ LOGD("num of factory : %d, codec type %d, %d", factories->n_values, video_codec_type, audio_codec_type);
+#endif
+ for (int i = 0 ; i < factories->n_values ; i++) {
+ gchar *hw_dec_info = NULL;
+ gchar (*sw_dec_info)[PLAYER_INI_MAX_STRLEN] = {NULL, };
+
+ factory = g_value_get_object(g_value_array_get_nth(factories, i));
+ if (!factory) {
+ LOGW("failed to get factory object");
+ continue;
+ }
+ klass = gst_element_factory_get_klass(factory);
+ factory_name = GST_OBJECT_NAME(factory);
+
+#ifdef __DEBUG__
+ LOGD("Klass [%s] Factory [%s]", klass, factory_name);
+#endif
+ if (g_strrstr(klass, "Codec/Decoder/Audio")) {
+ if (!player->need_audio_dec_sorting) {
+ LOGD("sorting is not required");
+ return NULL;
+ }
+ codec_type = audio_codec_type;
+ hw_dec_info = player->ini.audiocodec_element_hw;
+ sw_dec_info = player->ini.audiocodec_element_sw;
+ } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
+ if (!player->need_video_dec_sorting) {
+ LOGD("sorting is not required");
+ return NULL;
+ }
+ codec_type = video_codec_type;
+ hw_dec_info = player->ini.videocodec_element_hw;
+ sw_dec_info = player->ini.videocodec_element_sw;
+ } else {
+ continue;
+ }
+
+ if (g_strrstr(factory_name, hw_dec_info)) {
+ hw_dec_idx = i;
+ } else {
+ for (int j = 0; sw_dec_info[j][0] != '\0'; j++) {
+ if (strstr(factory_name, sw_dec_info[j])) {
+ last_sw_dec_idx = i;
+ if (first_sw_dec_idx == DEFAULT_IDX) {
+ first_sw_dec_idx = i;
+ }
+ }
+ }
+
+ if (first_sw_dec_idx == DEFAULT_IDX)
+ LOGW("unknown codec %s", factory_name);
+ }
+ }
+
+ if (hw_dec_idx == DEFAULT_IDX || first_sw_dec_idx == DEFAULT_IDX)
+ return NULL;
+
+ if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
+ if (hw_dec_idx < first_sw_dec_idx)
+ return NULL;
+ new_pos = first_sw_dec_idx;
+ rm_pos = hw_dec_idx + 1;
+ } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
+ if (last_sw_dec_idx < hw_dec_idx)
+ return NULL;
+ new_pos = last_sw_dec_idx + 1;
+ rm_pos = hw_dec_idx;
+ } else {
+ return NULL;
+ }
+
+ /* change position - insert H/W decoder according to the new position */
+ factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx));
+ if (!factory) {
+ LOGW("failed to get factory object");
+ return NULL;
+ }
+ new_factories = g_value_array_copy(factories);
+ g_value_init (&val, G_TYPE_OBJECT);
+ g_value_set_object (&val, factory);
+ g_value_array_insert(new_factories, new_pos, &val);
+ g_value_unset (&val);
+ g_value_array_remove(new_factories, rm_pos); /* remove previous H/W element */
+
+ for (int i = 0 ; i < new_factories->n_values ; i++) {
+ factory = g_value_get_object(g_value_array_get_nth(new_factories, i));
+ if (factory)
+ LOGD("[Re-arranged] Klass [%s] Factory [%s]",
+ gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory));
+ else
+ LOGE("[Re-arranged] failed to get factory object");
+ }
+
+ return new_factories;
+}
+
gint
_mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad,
GstCaps *caps, GstElementFactory *factory, gpointer data)
return;
}
- if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
- !__mmplayer_verify_gapless_play_path(player)) {
+ if (!__mmplayer_verify_gapless_play_path(player)) {
LOGD("decoding is finished.");
- __mmplayer_reset_gapless_state(player);
MMPLAYER_CMD_UNLOCK(player);
return;
}
- player->gapless.reconfigure = TRUE;
+ _mmplayer_set_reconfigure_state(player, TRUE);
+ MMPLAYER_CMD_UNLOCK(player);
/* check decodebin src pads whether they received EOS or not */
iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
if (!is_all_drained) {
LOGD("Wait util the all pads get EOS.");
- MMPLAYER_CMD_UNLOCK(player);
MMPLAYER_FLEAVE();
return;
}
/* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */
__mmplayer_deactivate_old_path(player);
- MMPLAYER_CMD_UNLOCK(player);
MMPLAYER_FLEAVE();
}
MMPLAYER_RETURN_IF_FAIL(player);
- player->video_decoded_cb = NULL;
- player->video_decoded_cb_user_param = NULL;
- player->video_stream_prerolled = false;
-
- player->audio_decoded_cb = NULL;
- player->audio_decoded_cb_user_param = NULL;
- player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT;
-
- player->audio_stream_changed_cb = NULL;
- player->audio_stream_changed_cb_user_param = NULL;
-
player->sent_bos = FALSE;
player->playback_rate = DEFAULT_PLAYBACK_RATE;
MMPLAYER_FENTER();
/* player->pipeline is already released before. */
-
MMPLAYER_RETURN_IF_FAIL(player);
+ player->video_decoded_cb = NULL;
+ player->video_decoded_cb_user_param = NULL;
+ player->video_stream_prerolled = false;
+
+ player->audio_decoded_cb = NULL;
+ player->audio_decoded_cb_user_param = NULL;
+ player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT;
+
+ player->audio_stream_changed_cb = NULL;
+ player->audio_stream_changed_cb_user_param = NULL;
+
mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", 0, NULL);
/* clean found audio decoders */
}
/* clean the uri list except original uri */
- if (player->uri_info.uri_list) {
+ if (player->uri_info.uri_list && g_list_length(player->uri_info.uri_list) > 1) {
original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
-
if (!original_uri)
LOGW("failed to get original uri info");
GList *uri_list = player->uri_info.uri_list;
for (; uri_list; uri_list = g_list_next(uri_list)) {
gchar *uri = uri_list->data;
- MMPLAYER_FREEIF(uri);
+ if (original_uri != uri)
+ MMPLAYER_FREEIF(uri);
}
- g_list_free(player->uri_info.uri_list);
- player->uri_info.uri_list = NULL;
}
/* clear the audio stream buffer list */
}
int
-_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, unsigned int wl_surface_id)
+_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, int wl_surface_id)
{
mmplayer_t *player = 0;
int prev_display_surface_type = 0;
/* videobin is not created yet, so we just set attributes related to display surface */
LOGD("store display attribute for given surface type(%d)", surface_type);
mm_player_set_attribute(handle, NULL, "display_surface_type", surface_type,
- "display_overlay", (int)wl_surface_id, NULL);
+ "display_overlay", wl_surface_id, NULL);
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
int
-_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_video_codec_type_e codec_type)
+_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_codec_type_e codec_type)
{
#define IDX_FIRST_SW_CODEC 0
mmplayer_t *player = (mmplayer_t *)hplayer;
case MM_PLAYER_STREAM_TYPE_AUDIO:
/* to support audio codec selection, codec info have to be added in ini file as below.
audio codec element hw = xxxx
- audio codec element sw = avdec */
+ audio codec element sw = avdec
+ and in case of audio hw codec is supported and selected,
+ audio filter elements should be applied depending on the hw capabilities.
+ */
if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
(!strcmp(player->ini.audiocodec_element_hw, ""))) ||
((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
int
_mmplayer_set_client_pid(MMHandleType hplayer, int pid)
{
- mmplayer_t* player = (mmplayer_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
return MM_ERROR_NONE;
}
+int
+_mmplayer_is_audio_control_available(MMHandleType hplayer, mmplayer_audio_control_opt_e opt, bool *available)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+ enum audio_element_id elem_id = MMPLAYER_A_NUM;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(available, MM_ERROR_INVALID_ARGUMENT);
+
+ *available = true;
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, (int *)&codec_type);
+
+ LOGD("current state %d, codec_type %d", MMPLAYER_CURRENT_STATE(player), codec_type);
+
+ if (codec_type == MM_PLAYER_CODEC_TYPE_SW)
+ return MM_ERROR_NONE;
+
+ /* in case of audio codec default type is HW */
+ switch(opt) {
+ case MM_PLAYER_AUDIO_CONTROL_OPT_EFFECT:
+ if (player->ini.support_audio_effect)
+ return MM_ERROR_NONE;
+ elem_id = MMPLAYER_A_FILTER;
+ break;
+ case MM_PLAYER_AUDIO_CONTROL_OPT_REPLAYGAIN:
+ if (player->ini.support_replaygain_control)
+ return MM_ERROR_NONE;
+ elem_id = MMPLAYER_A_RGVOL;
+ break;
+ case MM_PLAYER_AUDIO_CONTROL_OPT_PITCH:
+ if (player->ini.support_pitch_control)
+ return MM_ERROR_NONE;
+ elem_id = MMPLAYER_A_PITCH;
+ break;
+ case MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING:
+ if (player->ini.support_audio_effect)
+ return MM_ERROR_NONE;
+ break;
+ /* default case handling is not required */
+ }
+
+ if (MMPLAYER_CURRENT_STATE(player) < MM_PLAYER_STATE_READY) {
+ LOGW("audio control option [%d] is not available", opt);
+ *available = false;
+ } else {
+ /* setting pcm exporting option is allowed before READY state */
+ if (opt == MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING)
+ return MM_ERROR_PLAYER_INVALID_STATE;
+
+ /* check whether the audio filter exist or not after READY state,
+ because the sw codec could be added during auto-plugging in some cases */
+ if (!player->pipeline ||
+ !player->pipeline->audiobin ||
+ !player->pipeline->audiobin[elem_id].gst) {
+ LOGW("there is no audio elem [%d]", elem_id);
+ *available = false;
+ }
+ }
+
+ LOGD("audio control opt %d, available %d", opt, *available);
+
+ MMPLAYER_FLEAVE();
+
+ return MM_ERROR_NONE;
+}
+
static gboolean
__mmplayer_update_duration_value(mmplayer_t *player)
{
/* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
if (ret == MM_ERROR_NONE) {
- g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path);
if (_mmplayer_is_sdp_file(path)) {
LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc");
+ g_snprintf(data->uri, MM_MAX_URL_LEN, "rtsp-sdp://%s", path);
data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
} else {
+ g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path);
data->uri_type = MM_PLAYER_URI_TYPE_FILE;
}
} else if (ret == MM_ERROR_PLAYER_PERMISSION_DENIED) {