#define DEFAULT_PCM_OUT_SAMPLERATE 44100
#define DEFAULT_PCM_OUT_CHANNEL 2
+#define MQ_UNLINKED_CACHE_TIME (500 * GST_MSECOND)
+
/*---------------------------------------------------------------------------
| LOCAL CONSTANT DEFINITIONS: |
---------------------------------------------------------------------------*/
static gboolean __mmplayer_check_subtitle(mmplayer_t *player);
static int __mmplayer_handle_missed_plugin(mmplayer_t *player);
-static int __mmplayer_check_not_supported_codec(mmplayer_t *player, const gchar *factory_class, const gchar *mime);
static void __mmplayer_add_sink(mmplayer_t *player, GstElement *sink, gboolean first);
static void __mmplayer_del_sink(mmplayer_t *player, GstElement *sink);
static void __mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e type);
static void __mmplayer_set_pause_state(mmplayer_t *player);
static void __mmplayer_set_playing_state(mmplayer_t *player);
+static int __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index);
/*===========================================================================================
| |
| FUNCTION DEFINITIONS |
mainbin = player->pipeline->mainbin;
- MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
- MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
- MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
- MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
- MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
+ MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG); /* decodebin */
+ MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
+ MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
+ } else {
+ MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG); /* uridecodebin */
+ mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = NULL;
+ mainbin[MMPLAYER_M_SRC].gst = NULL;
+ }
/* Initialize Player values */
__mmplayer_initialize_gapless_play(player);
__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);
+ while (player->bus_watcher > 0) {
+ if (!MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time)) {
+ LOGW("MMPLAYER_BUS_WATCHER_WAIT_UNTIL() timeout has passed - bus_watcher (%d)",
+ player->bus_watcher);
+ break;
+ }
+ }
MMPLAYER_BUS_WATCHER_UNLOCK(player);
-
g_mutex_clear(&player->bus_watcher_mutex);
g_cond_clear(&player->bus_watcher_cond);
}
}
static GstPadProbeReturn
-__mmplayer_gst_selector_blocked(GstPad *pad, GstPadProbeInfo *info, gpointer data)
+__mmplayer_gst_combiner_blocked(GstPad *pad, GstPadProbeInfo *info, gpointer data)
{
LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
return GST_PAD_PROBE_OK;
}
static GstPadProbeReturn
-__mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer data)
+__mmplayer_gst_combiner_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer data)
{
GstPadProbeReturn ret = GST_PAD_PROBE_OK;
GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
return ret;
MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
- if (!caps_ret)
+ if (!caps_ret) {
+ GstStream *stream = NULL;
+
+ if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START)
+ goto ERROR;
+
+ gst_event_parse_stream (event, &stream);
+ if (stream == NULL) {
+ LOGW ("Got a STREAM_START event without a GstStream");
+ goto ERROR;
+ }
+
+ name = gst_stream_type_get_name(gst_stream_get_stream_type(stream));
+ gst_object_unref (stream);
+ }
+
+ if (!name)
goto ERROR;
if (strstr(name, "audio")) {
case GST_EVENT_EOS:
{
/* in case of gapless, drop eos event not to send it to sink */
+ MMPLAYER_RECONFIGURE_LOCK(player);
if (player->gapless.reconfigure && !player->msg_posted) {
LOGD("[%d] %s:%s EOS received but will be drop", stream_type, GST_DEBUG_PAD_NAME(pad));
ret = GST_PAD_PROBE_DROP;
}
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
break;
}
case GST_EVENT_STREAM_START:
fakesink = gst_element_factory_make("fakesink", NULL);
if (fakesink == NULL) {
LOGE("failed to create fakesink");
- goto EXIT;
+ return;
}
- /* store it as it's sink element */
- __mmplayer_add_sink(player, fakesink, FALSE);
-
- gst_bin_add(GST_BIN(pipeline), fakesink);
+ if (!gst_bin_add(GST_BIN(pipeline), fakesink)) {
+ LOGE("failed to add fakesink to pipeline");
+ goto ERROR;
+ }
/* link */
sinkpad = gst_element_get_static_pad(fakesink, "sink");
if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
LOGE("failed to link fakesink");
- gst_object_unref(GST_OBJECT(fakesink));
- goto EXIT;
+ goto ERROR;
}
if (strstr(name, "video")) {
g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
gst_element_set_state(fakesink, GST_STATE_PAUSED);
-EXIT:
+ /* store it as it's sink element */
+ __mmplayer_add_sink(player, fakesink, FALSE);
+
if (sinkpad)
gst_object_unref(GST_OBJECT(sinkpad));
MMPLAYER_FLEAVE();
return;
+
+ERROR:
+
+ if (sinkpad)
+ gst_object_unref(GST_OBJECT(sinkpad));
+
+ if (fakesink) {
+ gst_element_set_state(fakesink, GST_STATE_NULL);
+
+ if (!gst_bin_remove(GST_BIN(pipeline), fakesink))
+ gst_object_unref(GST_OBJECT(fakesink));
+ }
+
+ return;
}
static GstElement *
-__mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx)
+__mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx, mmplayer_track_type_e stream_type)
{
GstElement *pipeline = NULL;
- GstElement *concat = NULL;
+ g_autoptr(GstElement) concat = NULL;
+ g_autoptr(GstPad) srcpad = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
return NULL;
}
- LOGD("Create concat [%d] element", elem_idx);
+ srcpad = gst_element_get_static_pad(concat, "src");
+
+ LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
+ player->track[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
+ __mmplayer_gst_combiner_blocked, NULL, NULL);
+ player->track[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
+ __mmplayer_gst_combiner_event_probe, player, NULL);
- player->pipeline->mainbin[elem_idx].id = elem_idx;
- player->pipeline->mainbin[elem_idx].gst = concat;
gst_element_set_state(concat, GST_STATE_PAUSED);
pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
- gst_bin_add(GST_BIN(pipeline), concat);
+ if (!gst_bin_add(GST_BIN(pipeline), concat)) {
+ LOGE("failed to add concat to pipeline");
+ gst_element_set_state(concat, GST_STATE_NULL);
+ return NULL;
+ }
+
+ LOGD("Create concat [%d] element", elem_idx);
+
+ player->pipeline->mainbin[elem_idx].id = elem_idx;
+ player->pipeline->mainbin[elem_idx].gst = concat;
MMPLAYER_FLEAVE();
- return concat;
+ return g_steal_pointer(&concat);
}
static GstElement *
}
g_object_set(selector, "sync-streams", TRUE, NULL);
- player->pipeline->mainbin[elem_idx].id = elem_idx;
- player->pipeline->mainbin[elem_idx].gst = selector;
-
- /* player->track[stream_type].active_track_index = DEFAULT_TRACK; */
-
srcpad = gst_element_get_static_pad(selector, "src");
LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
player->track[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- __mmplayer_gst_selector_blocked, NULL, NULL);
+ __mmplayer_gst_combiner_blocked, NULL, NULL);
player->track[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
- __mmplayer_gst_selector_event_probe, player, NULL);
+ __mmplayer_gst_combiner_event_probe, player, NULL);
gst_element_set_state(selector, GST_STATE_PAUSED);
pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
- gst_bin_add(GST_BIN(pipeline), selector);
+ if (!gst_bin_add(GST_BIN(pipeline), selector)) {
+ LOGE("failed to add selector to pipeline");
+
+ if (player->track[stream_type].block_id != 0)
+ gst_pad_remove_probe (srcpad, player->track[stream_type].block_id);
+ player->track[stream_type].block_id = 0;
+
+ if (player->track[stream_type].event_probe_id != 0)
+ gst_pad_remove_probe (srcpad, player->track[stream_type].event_probe_id);
+ player->track[stream_type].event_probe_id = 0;
+
+ gst_object_unref(GST_OBJECT(srcpad));
+
+ gst_element_set_state(selector, GST_STATE_NULL);
+ gst_object_unref(GST_OBJECT(selector));
+ return NULL;
+ }
gst_object_unref(GST_OBJECT(srcpad));
+ player->pipeline->mainbin[elem_idx].id = elem_idx;
+ player->pipeline->mainbin[elem_idx].gst = selector;
+
MMPLAYER_FLEAVE();
return selector;
}
if (MMPLAYER_USE_DECODEBIN(player))
combiner = __mmplayer_gst_make_selector(player, elem_idx, stream_type);
else
- combiner = __mmplayer_gst_make_concat(player, elem_idx);
+ combiner = __mmplayer_gst_make_concat(player, elem_idx, stream_type);
if (!combiner)
goto ERROR;
}
/* link */
- sinkpad = gst_element_get_request_pad(combiner, "sink_%u");
+ sinkpad = gst_element_request_pad_simple(combiner, "sink_%u");
LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
sinkpad = NULL;
}
+ MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-added");
return;
}
/* change track to active pad */
active_index = player->track[type].active_track_index;
- if ((active_index != DEFAULT_TRACK) &&
+ if ((active_index != DEFAULT_TRACK_INDEX) &&
(__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) {
LOGW("failed to change %d type track to %d", type, active_index);
- player->track[type].active_track_index = DEFAULT_TRACK;
+ player->track[type].active_track_index = DEFAULT_TRACK_INDEX;
return;
}
mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
LOGD("display_surface_type (%d)", surface_type);
- if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) &&
+ if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) &&
(_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
LOGE("failed to acquire video overlay resource");
goto ERROR;
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
+ if (!(_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY) ||
+ _mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI)))
return;
attrs = MMPLAYER_GET_ATTRS(player);
win_roi_x, win_roi_y, win_roi_width, win_roi_height);
}
+static void __mmplayer_video_param_set_display_overlay_sync_ui(mmplayer_t *player)
+{
+ MMHandleType attrs = 0;
+ gchar *handle = NULL;
+
+ /* check video sinkbin is created */
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI))
+ return;
+
+ attrs = MMPLAYER_GET_ATTRS(player);
+ MMPLAYER_RETURN_IF_FAIL(attrs);
+
+ /* common case if using overlay surface */
+ mm_attrs_get_string_by_name(attrs, "exported_shell_handle", &handle);
+ MMPLAYER_RETURN_IF_FAIL(handle);
+
+ gst_video_overlay_set_wl_window_exported_shell_handle(
+ GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ handle);
+ LOGD("set video param: exported_shell_handle (%s)", handle);
+}
+
static void __mmplayer_video_param_set_display_overlay(mmplayer_t *player)
{
MMHandleType attrs = 0;
_mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
{
gboolean update_all_param = FALSE;
+ int curr_type = MM_DISPLAY_SURFACE_NUM;
MMPLAYER_FENTER();
- if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) {
+ if (!player || !player->pipeline || !player->pipeline->mainbin || !player->pipeline->videobin ||
+ !player->pipeline->videobin[MMPLAYER_V_BIN].gst ||
+ !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
LOGW("videosink is not ready yet");
return MM_ERROR_PLAYER_NOT_INITIALIZED;
}
+ mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type);
+
+ if (curr_type != MM_DISPLAY_SURFACE_OVERLAY && curr_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
+ LOGE("current type(%d) is wrong", curr_type);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
LOGE("invalid videosink [%s]", player->ini.videosink_element_overlay);
return MM_ERROR_PLAYER_INTERNAL;
if (!g_strcmp0(param_name, "update_all_param"))
update_all_param = TRUE;
+ if (curr_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
+ __mmplayer_video_param_set_display_overlay_sync_ui(player);
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+ }
if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
__mmplayer_video_param_set_display_overlay(player);
if (update_all_param || !g_strcmp0(param_name, "display_method"))
if (update_all_param)
__mmplayer_video_param_set_video_roi_area(player);
-
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-int
-_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
+static int __mmplayer_set_disable_overlay_option(mmplayer_t *player, bool disable)
{
gboolean disable_overlay = FALSE;
- mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
player->pipeline->videobin[MMPLAYER_V_SINK].gst,
MM_ERROR_PLAYER_NO_OP); /* invalid op */
g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
- if (audio_only == (bool)disable_overlay) {
- LOGE("It's the same with current setting: (%d)", audio_only);
+ if (disable == (bool)disable_overlay) {
+ LOGE("It's the same with current setting: (%d)", disable);
return MM_ERROR_NONE;
}
- if (audio_only) {
+ if (disable) {
LOGE("disable overlay");
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
/* release overlay resource */
if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
LOGE("failed to release overlay resource");
- goto ERROR;
+ return MM_ERROR_PLAYER_INTERNAL;
}
} else {
if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
LOGE("failed to acquire video overlay resource");
- goto ERROR;
+ return MM_ERROR_PLAYER_INTERNAL;
}
player->interrupted_by_resource = FALSE;
LOGD("enable overlay");
__mmplayer_video_param_set_display_overlay(player);
+ __mmplayer_video_param_set_display_overlay_sync_ui(player);
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
}
-ERROR:
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
int
-_mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
+_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
{
+ int ret = MM_ERROR_NONE;
mmplayer_t *player = (mmplayer_t *)hplayer;
- gboolean disable_overlay = FALSE;
MMPLAYER_FENTER();
-
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
- player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- MM_ERROR_PLAYER_NO_OP); /* invalid op */
- if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
- LOGW("Display control is not supported");
- return MM_ERROR_PLAYER_INTERNAL;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ ret = __mmplayer_set_disable_overlay_option(player, audio_only);
+ goto EXIT;
}
- g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
+ if (audio_only) {
+ MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
+ player->pipeline->videobin[MMPLAYER_V_SINK].gst,
+ MM_ERROR_PLAYER_NO_OP); /* invalid op */
- *paudio_only = (bool)disable_overlay;
+ __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
- LOGD("audio_only : %d", *paudio_only);
+ __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, INVALID_TRACK_INDEX);
- MMPLAYER_FLEAVE();
+ /* release decoder resource */
+ if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+ LOGE("failed to release video decoder resources");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+ player->can_support_codec &= ~FOUND_PLUGIN_VIDEO;
+ } else {
+ __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, DEFAULT_TRACK_INDEX);
+ }
- return MM_ERROR_NONE;
+EXIT:
+ mm_player_set_attribute(hplayer, NULL, MM_PLAYER_AUDIO_ONLY, (int)audio_only, (char *)NULL);
+
+ MMPLAYER_FLEAVE();
+ return ret;
}
int
MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", G_CALLBACK(__mmplayer_gst_audio_deinterleave_no_more_pads), (gpointer)player);
player->no_more_pad = FALSE;
} else {
- /* 4-2. create fakesink to extract interlevaed pcm */
+ /* 4-2. create fakesink to extract interleaved pcm */
LOGD("add audio fakesink for interleaved audio");
MMPLAYER_CREATE_ELEMENT(audiobin, extract_sink_id, "fakesink", "fakeaudiosink", *bucket, player);
if (!(player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK))
GList *l = NULL;
MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
gboolean ret = TRUE;
+ gint64 end_time = 0;
/* check DRC, if it is, destroy the prev bo list to create again */
if (player->video_bo_size != size) {
}
}
+ if (player->ini.video_bo_timeout > 0)
+ end_time = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND;
+
while (TRUE) {
/* get bo from list*/
for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
return tbm_bo_ref(tmp->bo);
}
}
- if (!ret) {
- LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
- MMPLAYER_VIDEO_BO_UNLOCK(player);
- return NULL;
- }
if (player->ini.video_bo_timeout <= 0) {
MMPLAYER_VIDEO_BO_WAIT(player);
} else {
- gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND;
- ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
+ ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, end_time);
+ if (!ret) {
+ LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
+ break;
+ }
}
- continue;
}
+
+ MMPLAYER_VIDEO_BO_UNLOCK(player);
+ return NULL;
}
static void
goto EXIT;
}
- if (surface_type != MM_DISPLAY_SURFACE_OVERLAY || player->set_mode.video_zc) {
+ if ((surface_type != MM_DISPLAY_SURFACE_OVERLAY &&
+ surface_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) ||
+ player->set_mode.video_zc) {
LOGD("skip creating the videoconv and rotator");
return MM_ERROR_NONE;
}
switch (surface_type) {
case MM_DISPLAY_SURFACE_OVERLAY:
+ /* fall through */
+ case MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI:
if (strlen(player->ini.videosink_element_overlay) > 0)
factory_name = player->ini.videosink_element_overlay;
break;
case MM_DISPLAY_SURFACE_REMOTE:
+ /* fall through */
case MM_DISPLAY_SURFACE_NULL:
if (strlen(player->ini.videosink_element_fake) > 0)
factory_name = player->ini.videosink_element_fake;
return MM_ERROR_PLAYER_INTERNAL;
}
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
+ if (surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) {
bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
goto ERROR;
}
- /* done. free allocated variables */
- g_list_free(element_bucket);
-
if (textbin[MMPLAYER_T_QUEUE].gst) {
GstPad *pad = NULL;
GstPad *ghostpad = NULL;
}
}
+ g_list_free(element_bucket);
+
return MM_ERROR_NONE;
ERROR:
+
g_list_free(element_bucket);
if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
__mmplayer_gst_create_text_sink_bin(mmplayer_t *player)
{
mmplayer_gst_element_t *textbin = NULL;
- GList *element_bucket = NULL;
int surface_type = 0;
gint i = 0;
LOGD("ERROR : releasing textbin");
- g_list_free(element_bucket);
-
/* release signal */
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
LOGI("subtitle duration is invalid, subtitle duration change "
"GST_CLOCK_TIME_NONE -> %" GST_TIME_FORMAT, GST_TIME_ARGS(duration));
}
- msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
+ msg.subtitle.duration = (unsigned long)GST_TIME_AS_MSECONDS(duration);
- LOGD("update subtitle : [%ld msec] %s", msg.subtitle.duration, (char *)msg.data);
+ LOGD("update subtitle : [%lu msec] %s", msg.subtitle.duration, (char *)msg.data);
MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
gst_buffer_unmap(buffer, &mapinfo);
gint64 adjusted_timestamp = 0;
GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, GST_PAD_PROBE_DROP);
- if (player->set_mode.subtitle_off) {
- LOGD("subtitle is OFF.");
- return TRUE;
- }
+ if (player->set_mode.subtitle_off)
+ return GST_PAD_PROBE_OK;
- if (player->adjust_subtitle_pos == 0) {
- LOGD("nothing to do");
- return TRUE;
- }
+ if (player->adjust_subtitle_pos == 0)
+ return GST_PAD_PROBE_OK;
cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
adjusted_timestamp = (gint64)cur_timestamp + ((gint64)player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
if (adjusted_timestamp < 0) {
LOGD("adjusted_timestamp under zero");
MMPLAYER_FLEAVE();
- return FALSE;
+ return GST_PAD_PROBE_DROP;
}
GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_INVALID_HANDLE);
/* cleanup stuffs */
- MMPLAYER_FREEIF(player->type);
+ MMPLAYER_FREEIF(player->type_caps_str);
player->no_more_pad = FALSE;
player->num_dynamic_pad = 0;
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
if (mainbin) {
- mmplayer_gst_element_t *audiobin = player->pipeline->audiobin;
- mmplayer_gst_element_t *videobin = player->pipeline->videobin;
- mmplayer_gst_element_t *textbin = player->pipeline->textbin;
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
gst_object_unref(bus);
if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
- MMPLAYER_FREEIF(audiobin);
- MMPLAYER_FREEIF(videobin);
- MMPLAYER_FREEIF(textbin);
+ MMPLAYER_FREEIF(player->pipeline->audiobin);
+ MMPLAYER_FREEIF(player->pipeline->videobin);
+ MMPLAYER_FREEIF(player->pipeline->textbin);
MMPLAYER_FREEIF(mainbin);
}
}
MMPLAYER_FREEIF(player->album_art);
- if (player->type_caps) {
- gst_caps_unref(player->type_caps);
- player->type_caps = NULL;
- }
-
if (player->v_stream_caps) {
gst_caps_unref(player->v_stream_caps);
player->v_stream_caps = NULL;
player->interrupted_by_resource = TRUE;
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_INTERRUPT_STARTED, NULL);
+
/* get last play position */
if (_mmplayer_gst_get_position(player, &pos) == MM_ERROR_NONE) {
msg.union_type = MM_MSG_UNION_TIME;
ret = _mmplayer_initialize_video_capture(player);
if (ret != MM_ERROR_NONE) {
- LOGE("failed to initialize video capture");
- goto ERROR;
+ LOGW("video capture is not supported");
+ /* do not handle as error for headless profile */
}
/* initialize resource manager */
player->pipeline->mainbin,
MM_ERROR_PLAYER_NOT_INITIALIZED);
- LOGD("set the pipeline state to READY");
+ if (player->pipeline->videobin && player->pipeline->videobin[MMPLAYER_V_BIN].gst) {
+ LOGD("set the videobin state to READY");
+ ret = _mmplayer_gst_set_state(player, player->pipeline->videobin[MMPLAYER_V_BIN].gst,
+ GST_STATE_READY, TRUE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
+
+ }
+
+ if (player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_BIN].gst) {
+ LOGD("set the audiobin state to READY");
+ ret = _mmplayer_gst_set_state(player, player->pipeline->audiobin[MMPLAYER_A_BIN].gst,
+ GST_STATE_READY, TRUE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
- /* set state to READY */
+ }
+
+ LOGD("set the pipeline state to READY");
ret = _mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
GST_STATE_READY, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
+
if (ret != MM_ERROR_NONE) {
LOGE("fail to change state to READY");
return MM_ERROR_PLAYER_INTERNAL;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_RETURN_VAL_IF_FAIL(duration, MM_ERROR_COMMON_INVALID_ARGUMENT);
- if (g_strrstr(player->type, "video/mpegts"))
+ if (g_strrstr(player->type_caps_str, "video/mpegts"))
__mmplayer_update_duration_value(player);
*duration = player->duration;
__mmplayer_update_content_type_info(mmplayer_t *player)
{
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->type);
+ MMPLAYER_RETURN_IF_FAIL(player && player->type_caps_str);
- if (__mmplayer_is_midi_type(player->type)) {
+ if (__mmplayer_is_midi_type(player->type_caps_str)) {
player->bypass_audio_effect = TRUE;
return;
}
return;
}
- if (g_strrstr(player->type, "application/x-hls")) {
+ if (g_strrstr(player->type_caps_str, "application/x-hls")) {
/* If it can't know exact type when it parses uri because of redirection case,
* it will be fixed by typefinder or when doing autoplugging.
*/
player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
player->streamer->is_adaptive_streaming = TRUE;
- } else if (g_strrstr(player->type, "application/dash+xml")) {
+ } else if (g_strrstr(player->type_caps_str, "application/dash+xml")) {
player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
player->streamer->is_adaptive_streaming = TRUE;
}
/* in case of TS, fixed buffering mode should be used because player can not get exact duration time */
- if ((player->streamer->is_adaptive_streaming) || (g_strrstr(player->type, "video/mpegts"))) {
+ if ((player->streamer->is_adaptive_streaming) || (g_strrstr(player->type_caps_str, "video/mpegts"))) {
player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
if (player->streamer->buffering_req.rebuffer_time <= MIN_BUFFERING_TIME) { /* if user did not set the rebuffer value */
MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
- /* store type string */
- if (player->type_caps) {
- gst_caps_unref(player->type_caps);
- player->type_caps = NULL;
- }
-
- player->type_caps = gst_caps_copy(caps);
- MMPLAYER_LOG_GST_CAPS_TYPE(player->type_caps);
-
- MMPLAYER_FREEIF(player->type);
- player->type = gst_caps_to_string(caps);
- if (player->type)
- LOGD("[handle: %p] media type %s found, probability %d%% / %d",
- player, player->type, probability, gst_caps_get_size(caps));
+ MMPLAYER_FREEIF(player->type_caps_str);
+ player->type_caps_str = gst_caps_to_string(caps);
+ LOGD("[handle: %p] media type %s found, probability %d%% / %d",
+ player, player->type_caps_str, probability, gst_caps_get_size(caps));
if ((!MMPLAYER_IS_RTSP_STREAMING(player)) &&
- (g_strrstr(player->type, "audio/x-raw-int"))) {
+ (g_strrstr(player->type_caps_str, "audio/x-raw-int"))) {
LOGE("not support media format");
if (player->msg_posted == FALSE) {
if (!_mmplayer_gst_create_decoder(player, pad, caps)) {
gboolean async = FALSE;
- LOGE("failed to autoplug %s", player->type);
+ LOGE("failed to autoplug %s", player->type_caps_str);
mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
/* NOTE : in case of ts streaming, player could not get the correct duration info *
* skip the pull mode(file or ring buffering) setting. */
if (dur_bytes > 0) {
- if (!g_strrstr(player->type, "video/mpegts")) {
+ if (!g_strrstr(player->type_caps_str, "video/mpegts")) {
type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
}
/* And, it still has a parent "player".
* You need to let the parent manage the object instead of unreffing the object directly.
*/
- gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
- gst_object_unref(queue2);
+ if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
+ LOGE("failed to remove queue2");
+ gst_object_unref(queue2);
+ }
queue2 = NULL;
}
* You need to let the parent manage the object instead of unreffing the object directly.
*/
- gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
- gst_object_unref(decodebin);
+ if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
+ LOGE("failed to remove decodebin");
+ gst_object_unref(decodebin);
+ }
decodebin = NULL;
}
return FALSE;
}
-static int
-__mmplayer_check_not_supported_codec(mmplayer_t *player, const gchar *factory_class, const gchar *mime)
+int
+_mmplayer_update_not_supported_codec_info(mmplayer_t *player, const gchar *factory_class, const gchar *mime)
{
MMPLAYER_FENTER();
return FALSE;
}
+ if (!MMPLAYER_USE_DECODEBIN(player)) {
+ if (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst)
+ g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst),
+ "uri", profile.uri, NULL);
+ }
+
SECURE_LOGD("next playback uri: %s", uri);
return TRUE;
}
}
num_of_uri = g_list_length(player->uri_info.uri_list);
+ if (!MMPLAYER_USE_DECODEBIN(player))
+ player->gapless.running = TRUE;
LOGD("repeat count = %d, num_of_list = %d", count, num_of_uri);
LOGD("there is no next uri and no repeat");
goto ERROR;
}
+
+ if (!MMPLAYER_USE_DECODEBIN(player)) {
+ if (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst)
+ g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst),
+ "uri", player->profile.uri, NULL);
+ }
+
LOGD("looping cnt %d", count);
} else {
/* gapless playback path */
g_ptr_array_set_size(selector->streams, 0);
gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
- gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
+ if (!gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst),
+ player->pipeline->mainbin[selectorId].gst)) {
+ LOGE("failed to remove selector");
+ gst_object_unref(player->pipeline->mainbin[selectorId].gst);
+ }
player->pipeline->mainbin[selectorId].gst = NULL;
selector = NULL;
player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
SECURE_LOGD("add original path : %s", uri);
} else {
- player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
- player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
-
+ g_free(g_list_nth_data(player->uri_info.uri_list, 0));
+ player->uri_info.uri_list = g_list_prepend(
+ g_list_delete_link(player->uri_info.uri_list, player->uri_info.uri_list), g_strdup(uri));
SECURE_LOGD("change original path : %s", uri);
}
} else {
MMPLAYER_FREEIF(caps_str);
/* There is no available codec. */
- __mmplayer_check_not_supported_codec(player, klass, mime);
+ _mmplayer_update_not_supported_codec_info(player, klass, mime);
}
gboolean
MMPLAYER_FREEIF(caps_str);
} else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
- LOGD("already video linked");
- ret = FALSE;
+ if((MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) || (MMPLAYER_IS_DASH_STREAMING(player))) {
+ LOGD("video is already linked, allow the stream switch");
+ ret = TRUE;
+ } else {
+ LOGD("video is already linked");
+ ret = FALSE;
+ }
} else {
LOGD("found new stream");
}
this function need to be updated according to the supported media format
@see player->ini.audio_offload_media_format */
- if (__mmplayer_is_only_mp3_type(player->type)) {
+ if (__mmplayer_is_only_mp3_type(player->type_caps_str)) {
LOGD("offload supportable media format type");
return TRUE;
}
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->attrs, FALSE);
- LOGD("current stream : %s, sink: %s", player->type, player->ini.audio_offload_sink_element);
+ LOGD("current stream : %s, sink: %s", player->type_caps_str, player->ini.audio_offload_sink_element);
if (!__mmplayer_is_offload_supported_type(player))
goto DONE;
LOGD("[handle: %p] found new element [%s] to link", player, factory_name);
/* store type string */
- if (player->type == NULL) {
- player->type = gst_caps_to_string(caps);
+ if (player->type_caps_str == NULL) {
+ player->type_caps_str = gst_caps_to_string(caps);
__mmplayer_update_content_type_info(player);
}
gint stype = 0;
gint width = 0;
GstStructure *str = NULL;
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
- /* don't make video because of not required */
- if ((stype == MM_DISPLAY_SURFACE_NULL) &&
- (!player->set_mode.video_export)) {
- LOGD("no need video decoding, expose pad");
- result = GST_AUTOPLUG_SELECT_EXPOSE;
- goto DONE;
+ /* parsebin in adaptivedemux get error if there is no parser */
+ if ((!g_strrstr(GST_ELEMENT_NAME(bin), "parsebin")) ||
+ ((!MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) && (!MMPLAYER_IS_DASH_STREAMING(player)))) {
+ mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
+
+ /* don't make video because of not required */
+ if ((stype == MM_DISPLAY_SURFACE_NULL) &&
+ (!player->set_mode.video_export)) {
+ LOGD("no need video decoding, expose pad");
+ result = GST_AUTOPLUG_SELECT_EXPOSE;
+ goto DONE;
+ }
}
/* get w/h for omx state-tune */
}
void
-_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad,
+_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *pad,
gpointer data)
{
- //mmplayer_t *player = (mmplayer_t *)data;
- GstCaps *caps = NULL;
+ int ret = MM_ERROR_NONE;
+ mmplayer_t *player = (mmplayer_t *)data;
+ mmplayer_gst_element_t *mainbin = player->pipeline->mainbin;
+ mmplayer_gst_element_t *videobin = player->pipeline->videobin;
+ gint timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- LOGD("[Decodebin2] pad-removed signal");
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && mainbin);
- caps = gst_pad_query_caps(new_pad, NULL);
- if (!caps) {
- LOGW("query caps is NULL");
+ LOGD("decoded pad %s:%s removed", GST_DEBUG_PAD_NAME(pad));
+
+ if (MMPLAYER_USE_DECODEBIN(player))
+ return;
+
+ if (!videobin || !g_str_has_prefix(GST_PAD_NAME (pad), "video"))
+ return;
+
+ __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
+
+ __mmplayer_del_sink(player, videobin[MMPLAYER_V_SINK].gst);
+
+ LOGD("remove videobin");
+ ret = _mmplayer_gst_set_state(player, videobin[MMPLAYER_V_BIN].gst,
+ GST_STATE_NULL, FALSE, timeout);
+ if (ret != MM_ERROR_NONE) {
+ LOGE("fail to change state of videobin to NULL");
return;
}
- gchar *caps_str = NULL;
- caps_str = gst_caps_to_string(caps);
+ if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), videobin[MMPLAYER_V_BIN].gst)) {
+ LOGE("failed to remove videobin");
+ gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
+ }
- LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
+ LOGD("remove concat");
+ ret = _mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_V_CONCAT].gst,
+ GST_STATE_NULL, FALSE, timeout);
+ if (ret != MM_ERROR_NONE) {
+ LOGE("fail to change state of concat to NULL");
+ return;
+ }
- MMPLAYER_FREEIF(caps_str);
- gst_caps_unref(caps);
+ if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_V_CONCAT].gst)) {
+ LOGE("failed to remove video concat");
+ gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_V_CONCAT].gst));
+ }
+
+ mainbin[MMPLAYER_M_V_CONCAT].gst = NULL;
+ mainbin[MMPLAYER_M_V_CONCAT].id = 0;
+ MMPLAYER_FREEIF(player->pipeline->videobin);
+
+ ret = __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY);
+ if (ret != MM_ERROR_NONE)
+ LOGE("failed to release overlay resources");
+
+ player->videodec_linked = 0;
+
+ MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-removed");
+ MMPLAYER_FLEAVE();
}
void
if (!__mmplayer_verify_gapless_play_path(player)) {
LOGD("decoding is finished.");
- MMPLAYER_CMD_UNLOCK(player);
- return;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ MMPLAYER_CMD_UNLOCK(player);
+ return;
+ }
}
- _mmplayer_set_reconfigure_state(player, TRUE);
- MMPLAYER_CMD_UNLOCK(player);
-
- MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL);
- __mmplayer_deactivate_old_path(player);
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ _mmplayer_set_reconfigure_state(player, TRUE);
+ MMPLAYER_CMD_UNLOCK(player);
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_FLUSH_BUFFER, NULL);
+ __mmplayer_deactivate_old_path(player);
+ } else {
+ player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_AUDIO] = FALSE;
+ player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
+ MMPLAYER_CMD_UNLOCK(player);
+ }
MMPLAYER_FLEAVE();
}
player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
/* 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_POST_MSG(player, MM_MESSAGE_FLUSH_BUFFER, NULL); /* post message for gapless */
__mmplayer_deactivate_old_path(player);
MMPLAYER_FLEAVE();
}
void
-_mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
+_mmplayer_gst_element_added(GstBin *bin, GstElement *element, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
const gchar *klass = NULL;
if (__mmplayer_add_dump_buffer_probe(player, element))
LOGD("add buffer probe");
- if (g_strrstr(klass, "Codec/Decoder/Audio")) {
- gchar *selected = NULL;
- selected = g_strdup(GST_ELEMENT_NAME(element));
- player->audio_decoders = g_list_append(player->audio_decoders, selected);
-
- /* update codec info */
- player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
- player->can_support_codec |= FOUND_PLUGIN_AUDIO;
- player->audiodec_linked = 1;
- } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
- /* update codec info */
- player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
- player->can_support_codec |= FOUND_PLUGIN_VIDEO;
- player->videodec_linked = 1;
- }
-
- if (g_strrstr(klass, "Demuxer/Adaptive")) {
- player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
- player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
-
- LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
- player->adaptive_info.limit.width, player->adaptive_info.limit.height);
-
- g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
- "max-bandwidth", player->adaptive_info.limit.bandwidth,
- "max-video-width", player->adaptive_info.limit.width,
- "max-video-height", player->adaptive_info.limit.height, NULL);
+ if (g_strrstr(klass, "Decoder")) {
+ if (g_strrstr(klass, "Audio")) {
+ player->audio_decoders = g_list_append(player->audio_decoders,
+ g_strdup(GST_ELEMENT_NAME(element)));
+ /* update codec info */
+ player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+ player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+ player->audiodec_linked = 1;
+ } else if (g_strrstr(klass, "Video")) {
+ GstElement *video_parse = player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst;
+ /* update codec info */
+ player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
+ player->can_support_codec |= FOUND_PLUGIN_VIDEO;
+ player->videodec_linked = 1;
+
+ if (video_parse) {
+ GstPad *srcpad = gst_element_get_static_pad (video_parse, "src");
+ if (srcpad) {
+ GstCaps *caps = NULL;
+ GstStructure *str = NULL;
+ const gchar *name = NULL;
+ gboolean caps_ret = TRUE;
+
+ MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD (srcpad, caps, str, name, caps_ret);
+ if (caps_ret && str) {
+ const gchar *stream_format = gst_structure_get_string (str, "stream-format");
+ if (stream_format && g_strrstr(stream_format, "byte-stream")) {
+ if ((g_object_class_find_property(G_OBJECT_GET_CLASS(video_parse), "config-interval"))) {
+ g_object_set(G_OBJECT(video_parse), "config-interval", -1, NULL);
+ LOGD("Send SPS and PPS Insertion every IDR frame");
+ }
+ }
+ }
+ gst_object_unref(GST_OBJECT(srcpad));
+ }
+ }
+ }
} else if (g_strrstr(klass, "Demuxer")) {
+ if (g_strrstr(klass, "Adaptive")) {
+ player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
+ player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
+
+ MMPLAYER_FREEIF(player->type_caps_str);
+
+ if (g_strrstr(factory_name, "hlsdemux")) {
+ player->type_caps_str = g_strdup("application/x-hls");
+ player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
+ } else if (g_strrstr(factory_name, "dashdemux")) {
+ player->type_caps_str = g_strdup("application/dash+xml");
+ player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
+ } else {
+ LOGE("not supported type");
+ return;
+ }
+ player->streamer->is_adaptive_streaming = TRUE;
+
+ if (player->streamer->buffering_req.prebuffer_time <= MIN_BUFFERING_TIME)
+ player->streamer->buffering_req.prebuffer_time = DEFAULT_PREBUFFERING_TIME;
+
+ LOGD("max variant limit: %d, %d, %d, prebuffer time: %d ms",
+ player->adaptive_info.limit.bandwidth,
+ player->adaptive_info.limit.width,
+ player->adaptive_info.limit.height,
+ player->streamer->buffering_req.prebuffer_time);
+
+ g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
+ "max-bitrate", player->adaptive_info.limit.bandwidth,
+ "max-video-width", player->adaptive_info.limit.width,
+ "max-video-height", player->adaptive_info.limit.height,
+ "low-watermark-time", (guint64)(player->streamer->buffering_req.prebuffer_time * GST_MSECOND),
+ NULL);
+ } else {
#ifdef __DEBUG__
- LOGD("plugged element is demuxer. take it");
+ LOGD("plugged element is demuxer. take it");
#endif
- player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
- player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
- }
-
- if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
- int surface_type = 0;
-
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
+ player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
+ player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
+ }
+ } else if (g_strrstr(klass, "Parser") && (g_strrstr(klass, "Video"))) {
+ player->pipeline->mainbin[MMPLAYER_M_V_PARSE].id = MMPLAYER_M_V_PARSE;
+ player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst = element;
}
- // to support trust-zone only
- if (g_strrstr(factory_name, "asfdemux")) {
- LOGD("set file-location %s", player->profile.uri);
- g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
- } else if (g_strrstr(factory_name, "legacyh264parse")) {
- LOGD("[%s] output-format to legacyh264parse", "mssdemux");
- g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
- } else if (g_strrstr(factory_name, "mpegaudioparse")) {
+ if (g_strrstr(factory_name, "mpegaudioparse")) {
if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
- (__mmplayer_is_only_mp3_type(player->type))) {
+ (__mmplayer_is_only_mp3_type(player->type_caps_str))) {
LOGD("[mpegaudioparse] set streaming pull mode.");
g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
}
- } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
- player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
- }
-
- if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
+ } else if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
(g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
+
LOGD("plugged element is multiqueue. take it %s", GST_ELEMENT_NAME(element));
+ /* set mq unlinked cache size to avoid not-linked error */
+ gboolean sync_by_running_time = FALSE;
+ g_object_get(G_OBJECT(element), "sync-by-running-time", &sync_by_running_time, NULL);
+ if (sync_by_running_time)
+ g_object_set(G_OBJECT(element), "unlinked-cache-time", MQ_UNLINKED_CACHE_TIME, NULL);
+
player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
- if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
- (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) ||
- (MMPLAYER_IS_DASH_STREAMING(player))) {
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
/* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
_mm_player_streaming_set_multiqueue(player->streamer, element);
_mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
}
-
}
return;
static void
__mmplayer_release_misc_post(mmplayer_t *player)
{
- char *original_uri = NULL;
+ gchar *original_uri = NULL;
MMPLAYER_FENTER();
/* player->pipeline is already released before. */
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);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_video_found", 0, MM_PLAYER_AUDIO_ONLY, 0, NULL);
/* clean found audio decoders */
if (player->audio_decoders) {
mm_player_set_attribute((MMHandleType)player, NULL, "profile_uri",
original_uri, (original_uri) ? strlen(original_uri) : (0), NULL);
-
+ MMPLAYER_FREEIF(original_uri);
}
/* clear the audio stream buffer list */
/* get subtitle attribute */
attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs)
- return FALSE;
+ MMPLAYER_RETURN_VAL_IF_FAIL(attrs, FALSE);
mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
- if (!subtitle_uri || !strlen(subtitle_uri))
+ if (!subtitle_uri || (strlen(subtitle_uri) == 0)) {
+ MMPLAYER_FLEAVE();
return FALSE;
+ }
SECURE_LOGD("subtitle uri is %s[%zu]", subtitle_uri, strlen(subtitle_uri));
- player->is_external_subtitle_present = TRUE;
MMPLAYER_FLEAVE();
for (; sig_list; sig_list = sig_list->next) {
item = sig_list->data;
- if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
+ if (item && item->obj) {
if (g_signal_handler_is_connected(item->obj, item->sig))
g_signal_handler_disconnect(item->obj, item->sig);
}
current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
// sync clock with current pipeline
- curr_clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
+ curr_clock = gst_element_get_clock(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
curr_time = gst_clock_get_time(curr_clock);
base_time = gst_element_get_base_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
if (GST_STATE_CHANGE_FAILURE == ret) {
LOGE("fail to state change.");
result = MM_ERROR_PLAYER_INTERNAL;
+ if (curr_clock)
+ gst_object_unref(curr_clock);
goto ERROR;
}
}
LOGD("seek time = %"G_GINT64_FORMAT", rate = %f", time, player->playback_rate);
event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
- if (event) {
- _mmplayer_gst_send_event_to_sink(player, event);
- } else {
+ if (!event) {
result = MM_ERROR_PLAYER_INTERNAL;
LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */
goto ERROR;
}
+ if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS) {
+ GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
+ if (GST_IS_ELEMENT(text_sink)) {
+ if (gst_element_send_event(text_sink, event))
+ LOGD("sending event[%s] to subtitle sink element [%s] success!",
+ GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(text_sink));
+ else
+ LOGE("sending event[%s] to subtitle sink element [%s] failed!",
+ GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(text_sink));
+ }
+ } else {
+ _mmplayer_gst_send_event_to_sink(player, event);
+ }
+
/* sync state with current pipeline */
gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
}
MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
}
+ player->is_external_subtitle_present = TRUE;
MMPLAYER_FLEAVE();
return result;
guint active_idx = 0;
GstStream *stream = NULL;
GList *streams = NULL;
- GstEvent *ev = NULL;
GstCaps *caps = NULL;
+ MMPLAYER_FENTER();
LOGD("Switching Streams... type: %d, index: %d", type, index);
player->track[type].active_track_index = index;
for (int i = 0; i < MM_PLAYER_TRACK_TYPE_MAX; i++) {
/* FIXME: need to consider the non display type or audio only in case of MM_PLAYER_TRACK_TYPE_VIDEO */
- if (player->track[i].total_track_num > 0) {
+ LOGD("track type:%d, total: %d, active: %d", i,
+ player->track[i].total_track_num, player->track[i].active_track_index);
+ if (player->track[i].total_track_num > 0 &&
+ player->track[i].active_track_index > INVALID_TRACK_INDEX) {
active_idx = player->track[i].active_track_index;
stream = g_ptr_array_index(player->track[i].streams, active_idx);
streams = g_list_append (streams, (gchar *)gst_stream_get_stream_id(stream));
}
}
- ev = gst_event_new_select_streams(streams);
- gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, ev);
- g_list_free(streams);
+ if (streams) {
+ LOGD("send select stream event");
+ gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst,
+ gst_event_new_select_streams(streams));
+ g_list_free(streams);
+ }
+
+ /* in paused state, seek to current pos to flush mq buffer and release waiting task */
+ if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
+ gint64 pos_nsec = GST_CLOCK_TIME_NONE;
+ if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
+ pos_nsec = player->last_position;
+
+ LOGD("current pos %" GST_TIME_FORMAT ", rate = %f", GST_TIME_ARGS(pos_nsec), player->playback_rate);
+
+ if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+ player->playback_rate, GST_FORMAT_TIME,
+ (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
+ GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE)) {
+ LOGW("failed to seek");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+ }
+
+ MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
player = (mmplayer_t *)hplayer;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_PLAYER_NOT_INITIALIZED);
if (!player->pipeline) {
LOGE("Track %d pre setting -> %d", type, index);
if (player->pipeline && player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst) {
LOGD("update max limit of %s", GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst));
g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
- "max-bandwidth", bandwidth, "max-video-width", width, "max-video-height", height, NULL);
+ "max-bitrate", bandwidth, "max-video-width", width, "max-video-height", height, NULL);
/* FIXME: seek to current position for applying new variant limitation */
}
}
p = gst_caps_get_structure(caps_a, 0);
-
- mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
-
gst_structure_get_int(p, "rate", &samplerate);
gst_structure_get_int(p, "channels", &channels);
* So, if it's not set yet, fill it with found data.
*/
if (!audio_codec) {
- if (g_strrstr(player->type, "audio/midi"))
+ if (g_strrstr(player->type_caps_str, "audio/midi"))
audio_codec = "MIDI";
- else if (g_strrstr(player->type, "audio/x-amr"))
+ else if (g_strrstr(player->type_caps_str, "audio/x-amr"))
audio_codec = "AMR";
- else if (g_strrstr(player->type, "audio/mpeg")
- && !g_strrstr(player->type, "mpegversion=(int)1"))
+ else if (g_strrstr(player->type_caps_str, "audio/mpeg")
+ && !g_strrstr(player->type_caps_str, "mpegversion=(int)1"))
audio_codec = "AAC";
else
audio_codec = "unknown";