diff options
author | Eunhae Choi <eunhae1.choi@samsung.com> | 2016-12-19 22:04:50 +0900 |
---|---|---|
committer | Eunhae Choi <eunhae1.choi@samsung.com> | 2016-12-19 22:04:50 +0900 |
commit | 72b0292cd5f5b2534758566ad2c1f1dfb481ad4f (patch) | |
tree | 8e0c9759a0c103ccfa818ddbdaf4f1801df0f52f | |
parent | b30dddbb1a4ac1a48c600b75f7451cacd463368b (diff) | |
download | libmm-player-72b0292cd5f5b2534758566ad2c1f1dfb481ad4f.tar.gz libmm-player-72b0292cd5f5b2534758566ad2c1f1dfb481ad4f.tar.bz2 libmm-player-72b0292cd5f5b2534758566ad2c1f1dfb481ad4f.zip |
[v0.6.17] add rtsp buffering patch
Change-Id: I283c0c24cf6514504862dc274a752e3442c931b0
-rw-r--r-- | packaging/libmm-player.spec | 2 | ||||
-rw-r--r-- | src/include/mm_player_priv.h | 2 | ||||
-rw-r--r-- | src/mm_player_priv.c | 281 |
3 files changed, 236 insertions, 49 deletions
diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 95dc388..b3339f3 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.16 +Version: 0.6.17 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index c223dc1..911dd62 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -657,6 +657,8 @@ typedef struct { gboolean is_subtitle_off; gboolean is_external_subtitle_present; + gboolean is_external_subtitle_added_now; + gboolean pending_resume; /* contents bitrate for buffering management */ guint bitrate[MM_PLAYER_STREAM_COUNT_MAX]; diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 0401c66..459e5be 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -373,6 +373,11 @@ _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag) LOGW("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec)); } + if (player->duration < 0) { + LOGW("duration : %lld is Non-Initialized !!! \n",player->duration); + player->duration = 0; + } + /* try to get streaming service type */ stream_service_type = __mmplayer_get_stream_service_type(player); mm_attrs_set_int_by_name(attrs, "streaming_type", stream_service_type); @@ -562,9 +567,6 @@ static gboolean __mmplayer_get_stream_service_type(mm_player_t* player) case STREAMING_SERVICE_VOD: LOGD("it's vod streaming"); break; - case STREAMING_SERVICE_NONE: - LOGE("should not get here"); - break; default: LOGE("should not get here"); } @@ -636,8 +638,12 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ int found = 0; #define MMPLAYER_MAX_SOUND_PRIORITY 3 - /* it's first time to update all content attrs. */ - _mmplayer_update_content_attrs(player, ATTR_ALL); + /* rtsp case, get content attrs by GstMessage */ + if (!MMPLAYER_IS_RTSP_STREAMING(player)) { + /* it's first time to update all content attrs. */ + _mmplayer_update_content_attrs( player, ATTR_ALL ); + } + /* set max sound priority to keep own sound and not to mute other's one */ mm_attrs_get_int_by_name(player->attrs, "content_video_found", &found); if (found) { @@ -1022,34 +1028,20 @@ __mmplayer_handle_buffering_message(mm_player_t* player) case MM_PLAYER_STATE_NONE: { if (current_state != MM_PLAYER_STATE_PAUSED) { - LOGD("set pause state during buffering\n"); - __gst_pause(player, TRUE); - - // to cover the weak-signal environment. - if (MMPLAYER_IS_RTSP_STREAMING(player)) { - unsigned long position = 0; - gint64 pos_msec = 0; - - LOGD("[RTSP] seek to the buffering start point\n"); - - if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position)) { - LOGE("failed to get position\n"); - break; - } - - /* key unit seek */ - pos_msec = position * G_GINT64_CONSTANT(1000000); - - __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0, - GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, - pos_msec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + /* rtsp streaming pause makes rtsp server stop sending data. */ + if (!MMPLAYER_IS_RTSP_STREAMING(player)) { + LOGD("set pause state during buffering\n"); + __gst_pause( player, TRUE ); } } } break; case MM_PLAYER_STATE_PLAYING: - __gst_pause(player, TRUE); + /*[shweta.agg] rtsp streaming pause makes rtsp server stop sending data. */ + if (!MMPLAYER_IS_RTSP_STREAMING(player)) { + __gst_pause ( player, TRUE ); + } break; case MM_PLAYER_STATE_PAUSED: @@ -1278,6 +1270,7 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ case GST_MESSAGE_BUFFERING: { MMMessageParamType msg_param = {0, }; + int bRet = MM_ERROR_NONE; if (!MMPLAYER_IS_STREAMING(player)) break; @@ -1299,18 +1292,53 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ MMPLAYER_CMD_LOCK(player); __mmplayer_update_buffer_setting(player, msg); - if (__mmplayer_handle_buffering_message(player) == MM_ERROR_NONE) { + bRet = __mmplayer_handle_buffering_message(player); + + if (bRet == MM_ERROR_NONE) { msg_param.connection.buffering = player->streamer->buffering_percent; MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param); + + if (MMPLAYER_IS_RTSP_STREAMING(player) && + player->pending_resume && + (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) { + + player->is_external_subtitle_added_now = FALSE; + player->pending_resume = FALSE; + _mmplayer_resume((MMHandleType)player); + } + if (MMPLAYER_IS_RTSP_STREAMING(player) && - (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) { + (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) { + if (player->doing_seek) { if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) { player->doing_seek = FALSE; MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL); - } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) + } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) { async_done = TRUE; + } + } + } + } else if (bRet == MM_ERROR_PLAYER_INVALID_STATE) { + if (!player->streamer) { + LOGW("player->streamer is NULL, so discarding the buffering percent update\n"); + break; + } + + if ((MMPLAYER_IS_LIVE_STREAMING(player)) && (MMPLAYER_IS_RTSP_STREAMING(player))) { + + LOGD("player->last_position=%lld , player->streamer->buffering_percent=%d \n", + GST_TIME_AS_SECONDS(player->last_position), player->streamer->buffering_percent); + + if ((GST_TIME_AS_SECONDS(player->last_position) <= 0) && (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)) { + msg_param.connection.buffering = player->streamer->buffering_percent; + MMPLAYER_POST_MSG( player, MM_MESSAGE_BUFFERING, &msg_param ); + } else { + LOGD("Not updating Buffering Message for Live RTSP case !!!\n"); } + } else { + msg_param.connection.buffering = player->streamer->buffering_percent; + MMPLAYER_POST_MSG( player, MM_MESSAGE_BUFFERING, &msg_param ); } } MMPLAYER_CMD_UNLOCK(player); @@ -1357,6 +1385,21 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ gst_element_state_get_name((GstState)newstate), gst_element_state_get_name((GstState)pending)); + if (newstate == GST_STATE_PLAYING) { + if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (player->pending_seek.is_pending)) { + + int retVal = MM_ERROR_NONE; + LOGD("trying to play from (%lu) pending position\n", player->pending_seek.pos); + + retVal = __gst_set_position( player, player->pending_seek.format, player->pending_seek.pos, TRUE ); + + if (MM_ERROR_NONE != retVal) + LOGE("failed to seek pending postion. just keep staying current position.\n"); + + player->pending_seek.is_pending = FALSE; + } + } + if (oldstate == newstate) { LOGD("pipeline reports state transition to old state"); break; @@ -1403,6 +1446,19 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) || (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING)) MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING); + + if (MMPLAYER_IS_RTSP_STREAMING(player) && (MMPLAYER_IS_LIVE_STREAMING(player))) { + + LOGD("Current Buffering Percent = %d",player->streamer->buffering_percent); + if (player->streamer->buffering_percent < 100) { + + MMMessageParamType msg_param = {0, }; + LOGW("Posting Buffering Completed Message to Application !!!"); + + msg_param.connection.buffering = 100; + MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param ); + } + } } if (player->gapless.stream_changed) { @@ -1529,6 +1585,54 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND; MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); } + + /* custom message for RTSP attribute : + RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged. + sdp which has contents info is received when rtsp connection is opened. + extract duration ,codec info , resolution from sdp and get it by GstMessage */ + if (!strcmp(structure_name, "rtspsrc_properties")) { + + gchar *audio_codec = NULL; + gchar *video_codec = NULL; + gchar *video_frame_size = NULL; + + gst_structure_get(gst_message_get_structure(msg), "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL); + LOGD("rtsp duration : %lld msec", GST_TIME_AS_MSECONDS(player->duration)); + __mmplayer_get_stream_service_type(player); + mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(player->duration)); + + gst_structure_get(gst_message_get_structure(msg), "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL); + LOGD("rtsp_audio_codec : %s", audio_codec); + if (audio_codec) + mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec); + + gst_structure_get(gst_message_get_structure(msg), "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL); + LOGD("rtsp_video_codec : %s", video_codec); + if (video_codec) + mm_attrs_set_string_by_name(player->attrs, "content_video_codec", video_codec); + + gst_structure_get(gst_message_get_structure(msg), "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL); + LOGD("rtsp_video_frame_size : %s", video_frame_size); + if (video_frame_size) { + + char *seperator = strchr(video_frame_size, '-'); + if (seperator) { + + char video_width[10]={0,}; + int frame_size_len = strlen(video_frame_size); + int separtor_len = strlen(seperator); + + strncpy(video_width,video_frame_size,(frame_size_len-separtor_len)); + mm_attrs_set_int_by_name(attrs, "content_video_width", atoi(video_width)); + + seperator++; + mm_attrs_set_int_by_name(attrs, "content_video_height", atoi(seperator)); + } + } + + if (mmf_attrs_commit(attrs)) + LOGE("failed to commit.\n"); + } } break; @@ -4679,7 +4783,9 @@ __mmplayer_gst_create_audio_pipeline(mm_player_t* player) g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL); - if (player->videodec_linked && player->ini.use_system_clock) { + + if ((MMPLAYER_IS_RTSP_STREAMING(player)) || + (player->videodec_linked && player->ini.use_system_clock)) { LOGD("system clock will be used.\n"); g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL); } @@ -7401,12 +7507,16 @@ int __gst_pause(mm_player_t* player, gboolean async) // @ g_timer_destroy(timer); return ret; - } else if (!player->video_stream_cb && (!player->pipeline->videobin) && (!player->pipeline->audiobin)) { - if (MMPLAYER_IS_RTSP_STREAMING(player)) - return ret; + + } else if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_stream_cb) && + (!player->pipeline->videobin) && (!player->pipeline->audiobin)) { + return MM_ERROR_PLAYER_CODEC_NOT_FOUND; - } else if (ret == MM_ERROR_NONE) + + } else if (ret == MM_ERROR_NONE) { + MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED); + } } /* generate dot file before returning error */ @@ -7486,7 +7596,19 @@ __gst_set_position(mm_player_t* player, int format, unsigned long position, gboo */ if (!player->duration) { if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) + { + /* [prasenjit.c] For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly. + * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */ + if ((MMPLAYER_IS_RTSP_STREAMING( player )) && (__mmplayer_get_stream_service_type(player) != STREAMING_SERVICE_LIVE)) { + player->pending_seek.is_pending = TRUE; + player->pending_seek.format = format; + player->pending_seek.pos = position; + player->doing_seek = FALSE; + MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL ); + return MM_ERROR_NONE; + } else goto SEEK_ERROR; + } player->duration = dur_nsec; } @@ -7516,6 +7638,21 @@ __gst_set_position(mm_player_t* player, int format, unsigned long position, gboo LOGD("seeking to(%lu) msec, duration is %d msec\n", position, dur_msec); + /* + [prasenjit.c] For rtspsrc stack , npt-start value coming from server is used for finding the current position. + But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing. + This causes problem is position calculation during normal pause resume scenarios also. + Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. + */ + if ((MMPLAYER_IS_RTSP_STREAMING( player )) && + (__mmplayer_get_stream_service_type(player) != STREAMING_SERVICE_LIVE)) { + if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec)) + LOGW("getting current position failed in seek\n"); + + player->last_position = pos_nsec; + g_object_set( player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL ); + } + if (player->doing_seek) { LOGD("not completed seek"); return MM_ERROR_PLAYER_DOING_SEEK; @@ -7542,12 +7679,28 @@ __gst_set_position(mm_player_t* player, int format, unsigned long position, gboo if (event) __gst_send_event_to_sink(player, event); - __gst_pause(player, FALSE); + if (!MMPLAYER_IS_RTSP_STREAMING(player)) + __gst_pause(player, FALSE); + } + + /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change). + that's why set position through property. */ + if ((MMPLAYER_IS_RTSP_STREAMING(player)) && + (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) && + (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) && + (!player->videodec_linked) && (!player->audiodec_linked)) { + + g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL); + LOGD("[%s] set position =%"GST_TIME_FORMAT, + gst_element_get_name(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec)); + player->doing_seek = FALSE; + MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL); + } else { + ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate, + GST_FORMAT_TIME, seek_flags, + GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); } - ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate, - GST_FORMAT_TIME, seek_flags, - GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); if (!ret) { LOGE("failed to set position. dur[%lu] pos[%lu] pos_msec[%llu]\n", dur_msec, position, pos_nsec); goto SEEK_ERROR; @@ -7673,16 +7826,12 @@ __gst_get_position(mm_player_t* player, int format, unsigned long* position) // case MM_PLAYER_POS_FORMAT_PERCENT: { - gint64 dur = 0; - gint64 pos = 0; - - dur = player->duration / GST_SECOND; - if (dur <= 0) { - LOGD("duration is [%d], so returning position 0\n", dur); + if (player->duration <= 0) { + LOGD("duration is [%lld], so returning position 0\n", player->duration); *position = 0; } else { - pos = pos_msec / GST_SECOND; - *position = pos * 100 / dur; + LOGD("postion is [%lld] msec , duration is [%lld] msec", pos_msec, player->duration); + *position = pos_msec * 100 / player->duration; } break; } @@ -8486,6 +8635,7 @@ _mmplayer_create_player(MMHandleType handle) // @ player->has_closed_caption = FALSE; player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER; player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER; + player->pending_resume = FALSE; if (player->ini.dump_element_keyword[0][0] == '\0') player->ini.set_dump_element_flag = FALSE; else @@ -8960,6 +9110,7 @@ _mmplayer_realize(MMHandleType hplayer) // @ player->audiosink_linked = 0; player->textsink_linked = 0; player->is_external_subtitle_present = FALSE; + player->is_external_subtitle_added_now = FALSE; /* set the subtitle ON default */ player->is_subtitle_off = FALSE; @@ -9626,6 +9777,12 @@ _mmplayer_pause(MMHandleType hplayer) // @ */ mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async); LOGD("prepare working mode : %s", (async ? "async" : "sync")); + + /* [shweta.agg] Changing back sync of rtspsrc to async */ + if (MMPLAYER_IS_RTSP_STREAMING(player)) { + LOGD("async prepare working mode for rtsp"); + async = TRUE; + } } break; @@ -9639,6 +9796,16 @@ _mmplayer_pause(MMHandleType hplayer) // @ LOGW("getting current position failed in paused\n"); player->last_position = pos_msec; + /* + [prasenjit.c] For rtspsrc stack , npt-start value coming from server is used for finding the current position. + But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing. + This causes problem is position calculation during normal pause resume scenarios also. + Currently during pause , we are sending the current position to rtspsrc module for position saving. + */ + if ((MMPLAYER_IS_RTSP_STREAMING( player )) && + (__mmplayer_get_stream_service_type(player) != STREAMING_SERVICE_LIVE)) { + g_object_set( player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL ); + } } break; } @@ -9675,6 +9842,12 @@ _mmplayer_resume(MMHandleType hplayer) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + /* [shweta.agg] Changing back sync mode rtspsrc to async */ + if ((MMPLAYER_IS_RTSP_STREAMING(player))) { + LOGD("async resume for rtsp case"); + async = TRUE; + } + ret = _mmplayer_sound_acquire_focus(&player->sound_focus); if (ret != MM_ERROR_NONE) { LOGE("failed to acquire sound focus.\n"); @@ -11044,6 +11217,7 @@ __mmplayer_initialize_next_play(mm_player_t *player) player->audiosink_linked = 0; player->textsink_linked = 0; player->is_external_subtitle_present = FALSE; + player->is_external_subtitle_added_now = FALSE; player->not_supported_codec = MISSING_PLUGIN_NONE; player->can_support_codec = FOUND_PLUGIN_NONE; player->pending_seek.is_pending = FALSE; @@ -13385,6 +13559,15 @@ __gst_send_event_to_sink(mm_player_t* player, GstEvent* event) MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE); MMPLAYER_RETURN_VAL_IF_FAIL(event, FALSE); + /*[shweta.agg] While adding subtitles in live feeds seek is getting called. + Adding defensive check in framework layer.*/ + if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) { + if (MMPLAYER_IS_LIVE_STREAMING (player)) { + LOGE ("Should not send seek event during live playback"); + return TRUE; + } + } + if (player->play_subtitle && !player->use_textoverlay) event2 = gst_event_copy((const GstEvent *)event); @@ -13402,7 +13585,7 @@ __gst_send_event_to_sink(mm_player_t* player, GstEvent* event) /* rtsp case, asyn_done is not called after seek during pause state */ if (MMPLAYER_IS_RTSP_STREAMING(player)) { - if (strstr(GST_EVENT_TYPE_NAME(event), "seek")) { + if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) { if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) { LOGD("RTSP seek completed, after pause state..\n"); player->doing_seek = FALSE; @@ -14292,6 +14475,8 @@ int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filep result = _mmplayer_sync_subtitle_pipeline(player); } else result = __mmplayer_change_external_subtitle_language(player, filepath); + + player->is_external_subtitle_added_now = TRUE; } MMPLAYER_FLEAVE(); |