From 5f2fbfe88b0ff8f6894cc81eb1c032d85c092f83 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Sat, 26 Apr 2025 16:17:23 -0400 Subject: [PATCH] report buffer full/empty from hls bus messages --- lib/http_handlers.h | 57 ++++++++++++++++++++++++-------------- renderers/video_renderer.c | 15 ++++++++-- renderers/video_renderer.h | 2 +- uxplay.cpp | 7 ++++- 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/lib/http_handlers.h b/lib/http_handlers.h index f7db4a9..25c83d9 100644 --- a/lib/http_handlers.h +++ b/lib/http_handlers.h @@ -279,10 +279,10 @@ http_handler_playback_info(raop_conn_t *conn, http_request_t *request, http_resp playback_info_t playback_info; playback_info.stallcount = 0; - playback_info.ready_to_play = true; // ???; - playback_info.playback_buffer_empty = false; // maybe need to get this from playbin - playback_info.playback_buffer_full = true; - playback_info.playback_likely_to_keep_up = true; + //playback_info.playback_buffer_empty = false; // maybe need to get this from playbin + //playback_info.playback_buffer_full = true; + //ayback_info.ready_to_play = true; // ???; + //ayback_info.playback_likely_to_keep_up = true; conn->raop->callbacks.on_video_acquire_playback_info(conn->raop->callbacks.cls, &playback_info); if (playback_info.duration == -1.0) { @@ -749,29 +749,44 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r const char *url = http_request_get_url(request); const char* upgrade = http_request_get_header(request, "Upgrade"); if (upgrade) { - //don't accept Upgrade: h2c request ? - return; + //don't accept Upgrade: h2c request ? + char *header_str = NULL; + http_request_get_header_string(request, &header_str); + logger_log(conn->raop->logger, LOGGER_INFO, + "%s\nhls upgrade request declined", header_str); + free (header_str); + return; } if (!strcmp(url, "/master.m3u8")){ char * master_playlist = get_master_playlist(conn->raop->airplay_video); - size_t len = strlen(master_playlist); - char * data = (char *) malloc(len + 1); - memcpy(data, master_playlist, len); - data[len] = '\0'; - *response_data = data; - *response_datalen = (int ) len; + if (master_playlist) { + size_t len = strlen(master_playlist); + char * data = (char *) malloc(len + 1); + memcpy(data, master_playlist, len); + data[len] = '\0'; + *response_data = data; + *response_datalen = (int ) len; + } else { + logger_log(conn->raop->logger, LOGGER_ERR,"requested master playlist %s not found", url); + *response_datalen = 0; + } + } else { char *media_playlist = get_media_playlist(conn->raop->airplay_video, url); - assert(media_playlist); - char *data = adjust_yt_condensed_playlist(media_playlist); - *response_data = data; - *response_datalen = strlen(data); - float duration = 0.0f; - int chunks = analyze_media_playlist(data, &duration); - logger_log(conn->raop->logger, LOGGER_INFO, - "Requested media_playlist %s has %5d chunks, total duration %9.3f secs", url, chunks, duration); - } + if (media_playlist) { + char *data = adjust_yt_condensed_playlist(media_playlist); + *response_data = data; + *response_datalen = strlen(data); + float duration = 0.0f; + int chunks = analyze_media_playlist(data, &duration); + logger_log(conn->raop->logger, LOGGER_INFO, + "Requested media_playlist %s has %5d chunks, total duration %9.3f secs", url, chunks, duration); + } else { + logger_log(conn->raop->logger, LOGGER_ERR,"requested media playlist %s not found", url); + *response_datalen = 0; + } + } http_response_add_header(response, "Access-Control-Allow-Headers", "Content-type"); http_response_add_header(response, "Access-Control-Allow-Origin", "*"); diff --git a/renderers/video_renderer.c b/renderers/video_renderer.c index efa396a..efd9b9b 100644 --- a/renderers/video_renderer.c +++ b/renderers/video_renderer.c @@ -52,6 +52,8 @@ static gint64 hls_seek_end = 0; static gint64 hls_duration; static gboolean hls_seek_enabled; static gboolean hls_playing; +static gboolean hls_buffer_empty; +static gboolean hls_buffer_full; typedef enum { @@ -232,6 +234,9 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, vide hls_seek_start = -1; hls_seek_end = -1; hls_duration = -1; + hls_buffer_empty = TRUE; + hls_buffer_empty = FALSE; + /* this call to g_set_application_name makes server_name appear in the X11 display window title bar, */ /* (instead of the program name uxplay taken from (argv[0]). It is only set one time. */ @@ -660,12 +665,16 @@ gboolean gstreamer_pipeline_bus_callback(GstBus *bus, GstMessage *message, void if (hls_video) { gint percent = -1; gst_message_parse_buffering(message, &percent); + hls_buffer_empty = TRUE; + hls_buffer_full = FALSE; if (percent > 0) { + hls_buffer_empty = FALSE; renderer_type[type]->buffering_level = percent; logger_log(logger, LOGGER_DEBUG, "Buffering :%d percent done", percent); if (percent < 100) { gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_PAUSED); } else { + hls_buffer_full = TRUE; gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_PLAYING); } } @@ -852,16 +861,18 @@ unsigned int video_reset_callback(void * loop) { return (unsigned int) TRUE; } -bool video_get_playback_info(double *duration, double *position, float *rate) { +bool video_get_playback_info(double *duration, double *position, float *rate, bool *buffer_empty, bool *buffer_full) { gint64 pos = 0; GstState state; *duration = 0.0; *position = -1.0; *rate = 0.0f; if (!renderer) { - return true; } + + *buffer_empty = (bool) hls_buffer_empty; + *buffer_full = (bool) hls_buffer_full; gst_element_get_state(renderer->pipeline, &state, NULL, 0); *rate = 0.0f; switch (state) { diff --git a/renderers/video_renderer.h b/renderers/video_renderer.h index 0a34805..1fbdbf4 100644 --- a/renderers/video_renderer.h +++ b/renderers/video_renderer.h @@ -63,7 +63,7 @@ unsigned int video_renderer_listen(void *loop, int id); void video_renderer_destroy (); void video_renderer_size(float *width_source, float *height_source, float *width, float *height); bool waiting_for_x11_window(); -bool video_get_playback_info(double *duration, double *position, float *rate); +bool video_get_playback_info(double *duration, double *position, float *rate, bool *buffer_empty, bool *buffer_full); int video_renderer_choose_codec(bool is_h265); unsigned int video_renderer_listen(void *loop, int id); unsigned int video_reset_callback(void *loop); diff --git a/uxplay.cpp b/uxplay.cpp index 1433bd8..77d4e73 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -2071,7 +2071,12 @@ extern "C" void on_video_acquire_playback_info (void *cls, playback_info_t *play int buffering_level; LOGD("on_video_acquire_playback info\n"); bool still_playing = video_get_playback_info(&playback_info->duration, &playback_info->position, - &playback_info->rate); + &playback_info->rate, + &playback_info->playback_buffer_empty, + &playback_info->playback_buffer_full); + playback_info->ready_to_play = true; //? + playback_info->playback_likely_to_keep_up = true; //? + LOGD("on_video_acquire_playback info done\n"); if (!still_playing) { LOGI(" video has finished, %f", playback_info->position);