From 380f729497ab17bad35feff41ea95faa015e22a5 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Thu, 7 Jan 2016 15:44:37 +0900 Subject: [PATCH] add internal api about buffer status cb with bytes info Change-Id: Ia1c89286226e6a795102473861952525ba3d40ef --- include/mobile/player_internal.h | 46 ++++++++++++++++++++ include/player_private.h | 2 + include/wearable/player_internal.h | 46 ++++++++++++++++++++ src/player.c | 2 +- src/player_internal.c | 87 ++++++++++++++++++++++++++++++++++++++ test/legacy_player_es_push_test.c | 42 ++++++++++-------- 6 files changed, 207 insertions(+), 18 deletions(-) diff --git a/include/mobile/player_internal.h b/include/mobile/player_internal.h index 75e1c39..210e72e 100644 --- a/include/mobile/player_internal.h +++ b/include/mobile/player_internal.h @@ -55,6 +55,18 @@ typedef struct { */ typedef void (*player_audio_pcm_extraction_cb)(player_audio_raw_data_s *audio_raw_frame, void *user_data); +/** + * @brief Called when the buffer level drops below the min size or exceeds the max size. + * @since_tizen 3.0 + * @remarks This API is used for media stream playback only. + * @param[in] status The buffer status + * @param[in] bytes The current buffer level bytes + * @param[in] user_data The user data passed from the callback registration function + * @see player_set_media_stream_buffer_status_cb_ex() + * @see player_set_media_stream_buffer_max_size() + * @see player_set_media_stream_buffer_min_threshold() + */ +typedef void (*player_media_stream_buffer_status_cb_ex) (player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data); /** * @brief Registers a callback function to be invoked when audio frame is decoded. Audio only contents is possible. If included video, error happens. @@ -110,6 +122,40 @@ int player_set_pcm_spec(player_h player, const char *format, int samplerate, int */ int player_set_streaming_playback_rate(player_h player, float rate); +/** + * @brief Registers a callback function to be invoked when buffer underrun or overflow is occurred. + * @since_tizen 3.0 + * @remarks This API is used for media stream playback only. + * @param[in] player The handle to the media player + * @param[in] type The type of target stream + * @param[in] callback The buffer status callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PLAYER_ERROR_NONE Successful + * @retval #PLAYER_ERROR_INVALID_STATE Invalid player state + * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The player state must be set to #PLAYER_STATE_IDLE by calling player_create() or player_unprepare(). + * @post player_media_stream_buffer_status_cb_ex() will be invoked. + * @see player_unset_media_stream_buffer_status_cb_ex() + * @see player_media_stream_buffer_status_cb_ex() + */ +int player_set_media_stream_buffer_status_cb_ex(player_h player, player_stream_type_e type, player_media_stream_buffer_status_cb_ex callback, void *user_data); + +/** + * @brief Unregisters the buffer status callback function. + * @since_tizen 3.0 + * @remarks This API is used for media stream playback only. + * @param[in] player The handle to the media player + * @param[in] type The type of target stream + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PLAYER_ERROR_NONE Successful + * @retval #PLAYER_ERROR_INVALID_STATE Invalid player state + * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter + * @see player_set_media_stream_buffer_status_cb() + */ +int player_unset_media_stream_buffer_status_cb_ex(player_h player, player_stream_type_e type); /** * @} diff --git a/include/player_private.h b/include/player_private.h index 81e0069..56d43f4 100644 --- a/include/player_private.h +++ b/include/player_private.h @@ -82,6 +82,8 @@ typedef enum { #endif _PLAYER_EVENT_TYPE_MEDIA_STREAM_VIDEO_BUFFER_STATUS, _PLAYER_EVENT_TYPE_MEDIA_STREAM_AUDIO_BUFFER_STATUS, + _PLAYER_EVENT_TYPE_MEDIA_STREAM_VIDEO_BUFFER_STATUS_WITH_INFO, + _PLAYER_EVENT_TYPE_MEDIA_STREAM_AUDIO_BUFFER_STATUS_WITH_INFO, _PLAYER_EVENT_TYPE_MEDIA_STREAM_VIDEO_SEEK, _PLAYER_EVENT_TYPE_MEDIA_STREAM_AUDIO_SEEK, _PLAYER_EVENT_TYPE_AUDIO_STREAM_CHANGED, diff --git a/include/wearable/player_internal.h b/include/wearable/player_internal.h index 9d9f3b8..6f168ff 100644 --- a/include/wearable/player_internal.h +++ b/include/wearable/player_internal.h @@ -55,6 +55,18 @@ typedef struct { */ typedef void (*player_audio_pcm_extraction_cb)(player_audio_raw_data_s *audio_raw_frame, void *user_data); +/** + * @brief Called when the buffer level drops below the min size or exceeds the max size. + * @since_tizen 3.0 + * @remarks This API is used for media stream playback only. + * @param[in] status The buffer status + * @param[in] bytes The current buffer level bytes + * @param[in] user_data The user data passed from the callback registration function + * @see player_set_media_stream_buffer_status_cb_ex() + * @see player_set_media_stream_buffer_max_size() + * @see player_set_media_stream_buffer_min_threshold() + */ +typedef void (*player_media_stream_buffer_status_cb_ex) (player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data); /** * @brief Registers a callback function to be invoked when audio frame is decoded. Audio only contents is possible. If included video, error happens. @@ -109,6 +121,40 @@ int player_set_pcm_spec(player_h player, const char *format, int samplerate, int */ int player_set_streaming_playback_rate(player_h player, float rate); +/** + * @brief Registers a callback function to be invoked when buffer underrun or overflow is occurred. + * @since_tizen 3.0 + * @remarks This API is used for media stream playback only. + * @param[in] player The handle to the media player + * @param[in] type The type of target stream + * @param[in] callback The buffer status callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PLAYER_ERROR_NONE Successful + * @retval #PLAYER_ERROR_INVALID_STATE Invalid player state + * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The player state must be set to #PLAYER_STATE_IDLE by calling player_create() or player_unprepare(). + * @post player_media_stream_buffer_status_cb_ex() will be invoked. + * @see player_unset_media_stream_buffer_status_cb_ex() + * @see player_media_stream_buffer_status_cb_ex() + */ +int player_set_media_stream_buffer_status_cb_ex(player_h player, player_stream_type_e type, player_media_stream_buffer_status_cb_ex callback, void *user_data); + +/** + * @brief Unregisters the buffer status callback function. + * @since_tizen 3.0 + * @remarks This API is used for media stream playback only. + * @param[in] player The handle to the media player + * @param[in] type The type of target stream + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PLAYER_ERROR_NONE Successful + * @retval #PLAYER_ERROR_INVALID_STATE Invalid player state + * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter + * @see player_set_media_stream_buffer_status_cb() + */ +int player_unset_media_stream_buffer_status_cb_ex(player_h player, player_stream_type_e type); /** * @} diff --git a/src/player.c b/src/player.c index 9039531..9a09aa8 100644 --- a/src/player.c +++ b/src/player.c @@ -2627,7 +2627,7 @@ int player_unset_video_stream_changed_cb(player_h player) return PLAYER_ERROR_NONE; } -static bool __media_stream_buffer_status_callback(player_stream_type_e type, player_media_stream_buffer_status_e status, void *user_data) +static bool __media_stream_buffer_status_callback(player_stream_type_e type, player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data) { player_s *handle = (player_s *)user_data; _player_event_e event_type; diff --git a/src/player_internal.c b/src/player_internal.c index f8b1ae2..93da242 100644 --- a/src/player_internal.c +++ b/src/player_internal.c @@ -121,3 +121,90 @@ int player_set_streaming_playback_rate(player_h player, float rate) } return ret; } + +static bool __media_stream_buffer_status_callback_ex(player_stream_type_e type, player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data) +{ + player_s *handle = (player_s *)user_data; + _player_event_e event_type; + + if (type == PLAYER_STREAM_TYPE_AUDIO) + event_type = _PLAYER_EVENT_TYPE_MEDIA_STREAM_AUDIO_BUFFER_STATUS_WITH_INFO; + else if (type == PLAYER_STREAM_TYPE_VIDEO) + event_type = _PLAYER_EVENT_TYPE_MEDIA_STREAM_VIDEO_BUFFER_STATUS_WITH_INFO; + else + return FALSE; + + LOGE("[%s] event type %d, status %d, bytes %llu", __FUNCTION__, event_type, status, bytes); + + if (handle->user_cb[event_type]) { + ((player_media_stream_buffer_status_cb_ex)handle->user_cb[event_type])(status, bytes, handle->user_data[event_type]); + } else { + LOGE("[%s][type:%d] buffer status cb was not set.", __FUNCTION__, type); + return FALSE; + } + + return TRUE; +} + + +int player_set_media_stream_buffer_status_cb_ex(player_h player, player_stream_type_e type, player_media_stream_buffer_status_cb_ex callback, void *user_data) +{ + int ret; + PLAYER_INSTANCE_CHECK(player); + PLAYER_NULL_ARG_CHECK(callback); + player_s *handle = (player_s *)player; + _player_event_e event_type; + + if (handle->state != PLAYER_STATE_IDLE) { + LOGE("[%s] PLAYER_ERROR_INVALID_STATE(0x%08x) : current state - %d", __FUNCTION__, PLAYER_ERROR_INVALID_STATE, handle->state); + return PLAYER_ERROR_INVALID_STATE; + } + /* the type can be expaned with default and text. */ + if ((type != PLAYER_STREAM_TYPE_VIDEO) && (type != PLAYER_STREAM_TYPE_AUDIO)) { + LOGE("[%s] PLAYER_ERROR_INVALID_PARAMETER(type : %d)", __FUNCTION__, type); + return PLAYER_ERROR_INVALID_PARAMETER; + } + + ret = mm_player_set_media_stream_buffer_status_callback(handle->mm_handle, type, (mm_player_media_stream_buffer_status_callback)__media_stream_buffer_status_callback_ex, (void *)handle); + + if (ret != MM_ERROR_NONE) + return __player_convert_error_code(ret, (char *)__FUNCTION__); + + if (type == PLAYER_STREAM_TYPE_VIDEO) + event_type = _PLAYER_EVENT_TYPE_MEDIA_STREAM_VIDEO_BUFFER_STATUS_WITH_INFO; + else + event_type = _PLAYER_EVENT_TYPE_MEDIA_STREAM_AUDIO_BUFFER_STATUS_WITH_INFO; + + LOGI("[%s] Event type : %d ", __FUNCTION__, type); + + handle->user_cb[event_type] = callback; + handle->user_data[event_type] = user_data; + + return PLAYER_ERROR_NONE; +} + +int player_unset_media_stream_buffer_status_cb_ex(player_h player, player_stream_type_e type) +{ + int ret; + PLAYER_INSTANCE_CHECK(player); + player_s *handle = (player_s *)player; + _player_event_e event_type; + + if (type == PLAYER_STREAM_TYPE_VIDEO) + event_type = _PLAYER_EVENT_TYPE_MEDIA_STREAM_VIDEO_BUFFER_STATUS_WITH_INFO; + else if (type == PLAYER_STREAM_TYPE_AUDIO) + event_type = _PLAYER_EVENT_TYPE_MEDIA_STREAM_AUDIO_BUFFER_STATUS_WITH_INFO; + else + return PLAYER_ERROR_INVALID_PARAMETER; + + handle->user_cb[event_type] = NULL; + handle->user_data[event_type] = NULL; + + LOGI("[%s] Event type : %d ", __FUNCTION__, type); + + ret = mm_player_set_media_stream_buffer_status_callback(handle->mm_handle, type, NULL, NULL); + if (ret != MM_ERROR_NONE) + return __player_convert_error_code(ret, (char *)__FUNCTION__); + else + return PLAYER_ERROR_NONE; +} diff --git a/test/legacy_player_es_push_test.c b/test/legacy_player_es_push_test.c index 08dbc3e..6b51ef8 100644 --- a/test/legacy_player_es_push_test.c +++ b/test/legacy_player_es_push_test.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #ifdef HAVE_WAYLAND @@ -199,7 +200,7 @@ static int app_pause(void *data) } if (ad->player_handle == NULL) { - printf("player_handle is NULL"); + LOGE("player_handle is NULL"); return -1; } @@ -208,14 +209,14 @@ static int app_pause(void *data) ad->feeding_thread_id = 0; } - player_unset_media_stream_buffer_status_cb(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO); - player_unset_media_stream_buffer_status_cb(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO); + player_unset_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO); + player_unset_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO); player_unset_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO); player_unset_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO); ret = player_unprepare(ad->player_handle); if (ret != PLAYER_ERROR_NONE) { - printf("player_unprepare failed : 0x%x", ret); + LOGE("player_unprepare failed : 0x%x", ret); return false; } @@ -228,7 +229,7 @@ static int app_pause(void *data) /* destroy player handle */ ret = player_destroy(ad->player_handle); if (ret != PLAYER_ERROR_NONE) { - printf("player_destroy failed : 0x%x", ret); + LOGE("player_destroy failed : 0x%x", ret); return false; } @@ -454,20 +455,24 @@ static void feed_video_data_thread_func(void *data) } } -void _video_buffer_status_cb(player_media_stream_buffer_status_e status, void *user_data) +void _video_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data) { - if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) - LOGE("video buffer is underrun state"); - else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) - LOGE("video buffer is overrun state"); + if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) { + LOGE("video buffer is underrun state, current level byte = %llu", bytes); + } + else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) { + LOGE("video buffer is overrun state, current level byte = %llu", bytes); + } } -void _audio_buffer_status_cb(player_media_stream_buffer_status_e status, void *user_data) +void _audio_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data) { - if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) - LOGE("audio buffer is underrun state"); - else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) - LOGE("audio buffer is overrun state"); + if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) { + LOGE("audio buffer is underrun state, current level byte = %llu", bytes); + } + else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) { + LOGE("audio buffer is overrun state, current level byte = %llu", bytes); + } } void _video_seek_data_cb(unsigned long long offset, void *user_data) @@ -517,12 +522,15 @@ static int app_reset(bundle *b, void *data) media_format_set_video_width(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_WIDTH); media_format_set_video_height(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_HEIGHT); - ret = player_set_media_stream_buffer_status_cb(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, _video_buffer_status_cb, (void *)ad); + player_set_media_stream_buffer_max_size(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, (unsigned long long)800*1024); + player_set_media_stream_buffer_min_threshold(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, 50); + + ret = player_set_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, _video_buffer_status_cb_ex, (void *)ad); if (ret != PLAYER_ERROR_NONE) { LOGE("player set video buffer status cb failed : 0x%x", ret); goto FAILED; } - ret = player_set_media_stream_buffer_status_cb(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO, _audio_buffer_status_cb, (void *)ad); + ret = player_set_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO, _audio_buffer_status_cb_ex, (void *)ad); if (ret != PLAYER_ERROR_NONE) { LOGE("player set audio buffer status cb failed : 0x%x", ret); goto FAILED; -- 2.7.4