static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
static int __mmplayer_start_streaming_ext(mm_player_t *player);
static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
-static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
static void __mmplayer_check_pipeline(mm_player_t* player);
mm_player_t* player = 0;
int prev_display_surface_type = 0;
void *prev_display_overlay = NULL;
- const gchar *klass = NULL;
- gchar *cur_videosink_name = NULL;
- int ret = 0;
- int i = 0;
- int num_of_dec = 2; /* DEC1, DEC2 */
MMPLAYER_FENTER();
player = MM_PLAYER_CAST(handle);
+ /* check video sinkbin is created */
+ if (__mmplayer_video_param_check_video_sink_bin(player) == MM_ERROR_NONE) {
+ LOGE("Videosink is already created");
+ return MM_ERROR_NONE;
+ }
+
+ LOGD("videosink element is not yet ready");
+
if (surface_type >= MM_DISPLAY_SURFACE_NUM) {
LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
MMPLAYER_FLEAVE();
return MM_ERROR_PLAYER_INTERNAL;
}
- /* check videosink element is created */
- if (!player->pipeline || !player->pipeline->videobin ||
- !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
- LOGD("videosink element is not yet ready");
-
- /* 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_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
- mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit attribute");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
- } else {
- /* get player command status */
- if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE)) {
- LOGE("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command", player->cmd);
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INVALID_STATE;
- }
-
- /* surface change */
- for (i = 0 ; i < num_of_dec ; i++) {
- if (player->pipeline->mainbin &&
- player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) {
- GstElementFactory *decfactory;
- decfactory = gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
-
- klass = gst_element_factory_get_metadata(decfactory, GST_ELEMENT_METADATA_KLASS);
- if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
- if ((prev_display_surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (surface_type == MM_DISPLAY_SURFACE_REMOTE)) {
- ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, "fakesink", surface_type, display_overlay);
- if (ret) {
- goto ERROR_CASE;
- } else {
- LOGW("success to changing display surface(%d)", surface_type);
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
- }
- } else if ((prev_display_surface_type == MM_DISPLAY_SURFACE_REMOTE) && (surface_type == MM_DISPLAY_SURFACE_OVERLAY)) {
- ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_overlay, surface_type, display_overlay);
- if (ret) {
- goto ERROR_CASE;
- } else {
- LOGW("success to changing display surface(%d)", surface_type);
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
- }
- } else {
- LOGE("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface", surface_type, cur_videosink_name);
- ret = MM_ERROR_PLAYER_INTERNAL;
- goto ERROR_CASE;
- }
- }
- }
- }
- }
-
-ERROR_CASE:
- /* rollback to previous attributes */
- mm_attrs_set_int_by_name(player->attrs, "display_surface_type", prev_display_surface_type);
- mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
+ /* 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_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
+ mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit attributes to rollback");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- MMPLAYER_FLEAVE();
- return ret;
-}
-
-/* NOTE : It does not support some use cases, eg using colorspace converter */
-int
-__mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
-{
- GstPad *src_pad_dec = NULL;
- GstPad *sink_pad_videosink = NULL;
- GstPad *sink_pad_videobin = NULL;
- GstClock *clock = NULL;
- MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
- int ret = MM_ERROR_NONE;
- gboolean is_audiobin_created = TRUE;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- LOGD("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
- LOGD("surface type(%d), display overlay(%x)", surface_type, display_overlay);
-
- /* get information whether if audiobin is created */
- if (!player->pipeline->audiobin ||
- !player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
- LOGW("audiobin is null, this video content may not have audio data");
- is_audiobin_created = FALSE;
- }
-
- /* get current state of player */
- previous_state = MMPLAYER_CURRENT_STATE(player);
- LOGD("previous state(%d)", previous_state);
-
-
- /* get src pad of decoder and block it */
- src_pad_dec = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
- if (!src_pad_dec) {
- LOGE("failed to get src pad from decode in mainbin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- if (player->seek_state == MMPLAYER_SEEK_NONE && previous_state == MM_PLAYER_STATE_PLAYING) {
- LOGW("trying to block pad(video)");
-// if (!gst_pad_set_blocked(src_pad_dec, TRUE))
- gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- NULL, NULL, NULL);
- {
- LOGE("failed to set block pad(video)");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- LOGW("pad is blocked(video)");
- } else {
- /* no data flows, so no need to do pad_block */
- if (player->seek_state != MMPLAYER_SEEK_NONE)
- LOGW("not completed seek(%d), do nothing", player->seek_state);
-
- LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
- }
-
- /* remove pad */
- if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
- GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin)))) {
- LOGE("failed to remove previous ghost_pad for videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* change state of videobin to NULL */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- LOGE("failed to change state of videobin to NULL");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* unlink between decoder and videobin and remove previous videosink from videobin */
- gst_element_unlink(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
- if (!gst_bin_remove(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst))) {
- LOGE("failed to remove former videosink from videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
-
- /* create a new videosink and add it to videobin */
- player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, "videosink");
- if (!player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
- LOGE("failed to create videosink element\n");
+ LOGE("failed to commit attribute");
MMPLAYER_FLEAVE();
return MM_ERROR_PLAYER_INTERNAL;
}
- gst_bin_add(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
- __mmplayer_add_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
- g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
-
- /* save attributes */
- if (player->attrs) {
- /* set a new display surface type */
- mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
- /* set a new diplay overlay */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- LOGD("save attributes related to video display surface : id = %d", *(int*)display_overlay);
- mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
- break;
- default:
- LOGE("invalid type(%d) for changing display surface", surface_type);
- MMPLAYER_FLEAVE();
- return MM_ERROR_INVALID_ARGUMENT;
- }
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- } else {
- LOGE("player->attrs is null, failed to save attributes");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* update video param */
- if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "update_all_param")) {
- LOGE("failed to update video param");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* change state of videobin to READY */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- LOGE("failed to change state of videobin to READY");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* change ghostpad */
- sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
- if (!sink_pad_videosink) {
- LOGE("failed to get sink pad from videosink element");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
- if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE)) {
- LOGE("failed to set active to ghost_pad");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- if (FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
- LOGE("failed to change ghostpad for videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- gst_object_unref(sink_pad_videosink);
-
- /* link decoder with videobin */
- sink_pad_videobin = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
- if (!sink_pad_videobin) {
- LOGE("failed to get sink pad from videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- if (GST_PAD_LINK_OK != gst_pad_link(src_pad_dec, sink_pad_videobin)) {
- LOGE("failed to link");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- gst_object_unref(sink_pad_videobin);
-
- /* clock setting for a new videosink plugin */
- /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
- so we set it from audiosink plugin or pipeline(system clock) */
- if (!is_audiobin_created) {
- LOGW("audiobin is not created, get clock from pipeline..");
- clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
- } else {
- clock = GST_ELEMENT_CLOCK(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
- }
- if (clock) {
- GstClockTime now;
- GstClockTime base_time;
- LOGD("set the clock to videosink");
- gst_element_set_clock(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
- clock = GST_ELEMENT_CLOCK(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
- if (clock) {
- LOGD("got clock of videosink");
- now = gst_clock_get_time(clock);
- base_time = GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
- LOGD("at time %" GST_TIME_FORMAT ", base %"
- GST_TIME_FORMAT, GST_TIME_ARGS(now), GST_TIME_ARGS(base_time));
- } else {
- LOGE("failed to get clock of videosink after setting clock");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- } else
- LOGW("failed to get clock, maybe it is the time before first playing");
-
- if (player->seek_state == MMPLAYER_SEEK_NONE && previous_state == MM_PLAYER_STATE_PLAYING) {
- /* change state of videobin to PAUSED */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
- if (ret != GST_STATE_CHANGE_FAILURE) {
- LOGW("change state of videobin to PLAYING, ret(%d)", ret);
- } else {
- LOGE("failed to change state of videobin to PLAYING");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* release blocked and unref src pad of video decoder */
- #if 0
- if (!gst_pad_set_blocked(src_pad_dec, FALSE)) {
- LOGE("failed to set pad blocked FALSE(video)");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- #endif
- LOGW("pad is unblocked(video)");
- } else {
- if (player->seek_state != MMPLAYER_SEEK_NONE)
- LOGW("not completed seek(%d)", player->seek_state);
- /* change state of videobin to PAUSED */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
- if (ret != GST_STATE_CHANGE_FAILURE) {
- LOGW("change state of videobin to PAUSED, ret(%d)", ret);
- } else {
- LOGE("failed to change state of videobin to PLAYING");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* already skipped pad block */
- LOGD("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
- }
-
- /* do get/set position for new videosink plugin */
- {
- gint64 position = 0;
-
- LOGD("do get/set position for new videosink plugin");
- if (__mmplayer_gst_get_position(player, &position)) {
- LOGE("failed to get position");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* key unit seek */
- ret = __mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
- GST_FORMAT_TIME, (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
- GST_SEEK_TYPE_SET, position,
- GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- if (!ret) {
- LOGE("failed to set position");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- }
-
- if (src_pad_dec)
- gst_object_unref(src_pad_dec);
- LOGD("success to change sink");
MMPLAYER_FLEAVE();
-
return MM_ERROR_NONE;
}
-
/* Note : if silent is true, then subtitle would not be displayed. :*/
int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
{