mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
add a callback to detect EOS in HLS videos
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
#include "video_renderer.h"
|
||||
#include "../lib/raop.h"
|
||||
|
||||
#define SECOND_IN_NSECS 1000000000UL
|
||||
#define SECOND_IN_MICROSECS 1000000
|
||||
@@ -46,7 +45,6 @@ static bool hls_video = false;
|
||||
static bool use_x11 = false;
|
||||
#endif
|
||||
static bool logger_debug = false;
|
||||
static bool video_terminate = false;
|
||||
static gint64 hls_requested_start_position = 0;
|
||||
static gint64 hls_seek_start = 0;
|
||||
static gint64 hls_seek_end = 0;
|
||||
@@ -77,7 +75,6 @@ typedef enum {
|
||||
} GstPlayFlags;
|
||||
|
||||
#define NCODECS 3 /* renderers for h264,h265, and jpeg images */
|
||||
static raop_t * raop = NULL;
|
||||
|
||||
struct video_renderer_s {
|
||||
GstElement *appsrc, *pipeline;
|
||||
@@ -86,7 +83,7 @@ struct video_renderer_s {
|
||||
bool autovideo;
|
||||
int id;
|
||||
char *uri;
|
||||
gboolean terminate;
|
||||
gboolean eos;
|
||||
gint64 duration;
|
||||
gint buffering_level;
|
||||
#ifdef X_DISPLAY_FIX
|
||||
@@ -232,13 +229,11 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, video
|
||||
GstCaps *caps = NULL;
|
||||
bool rtp = (bool) strlen(rtp_pipeline);
|
||||
hls_video = (uri != NULL);
|
||||
raop = NULL;
|
||||
/* videosink choices that are auto */
|
||||
auto_videosink = (strstr(videosink, "autovideosink") || strstr(videosink, "fpsdisplaysink"));
|
||||
|
||||
logger = render_logger;
|
||||
logger_debug = (logger_get_level(logger) >= LOGGER_DEBUG);
|
||||
video_terminate = false;
|
||||
hls_seek_enabled = FALSE;
|
||||
hls_playing = FALSE;
|
||||
hls_seek_start = -1;
|
||||
@@ -284,6 +279,7 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, video
|
||||
renderer_type[i]->bus = NULL;
|
||||
renderer_type[i]->appsrc = NULL;
|
||||
renderer_type[i]->uri = NULL;
|
||||
renderer_type[i]->eos = FALSE;
|
||||
if (hls_video) {
|
||||
renderer_type[i]->uri = (char *) calloc(strlen(uri) + 1, sizeof(char));
|
||||
memcpy(renderer_type[i]->uri, uri, strlen(uri));
|
||||
@@ -479,11 +475,10 @@ void video_renderer_resume() {
|
||||
}
|
||||
}
|
||||
|
||||
void video_renderer_start( void * opaque) {
|
||||
void video_renderer_start() {
|
||||
GstState state;
|
||||
const gchar *state_name;
|
||||
if (hls_video) {
|
||||
raop = (raop_t *) opaque;
|
||||
g_object_set (G_OBJECT (renderer->pipeline), "uri", renderer->uri, NULL);
|
||||
gst_element_set_state (renderer->pipeline, GST_STATE_PAUSED);
|
||||
gst_element_get_state(renderer->pipeline, &state, NULL, 1000 * GST_MSECOND);
|
||||
@@ -492,7 +487,6 @@ void video_renderer_start( void * opaque) {
|
||||
return;
|
||||
}
|
||||
/* when not hls, start both h264 and h265 pipelines; will shut down the "wrong" one when we know the codec */
|
||||
raop = NULL;
|
||||
for (int i = 0; i < n_renderers; i++) {
|
||||
gst_element_set_state (renderer_type[i]->pipeline, GST_STATE_PAUSED);
|
||||
gst_element_get_state(renderer_type[i]->pipeline, &state, NULL, 1000 * GST_MSECOND);
|
||||
@@ -867,7 +861,6 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m
|
||||
if (!hls_video) {
|
||||
gst_bus_set_flushing(bus, TRUE);
|
||||
gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_READY);
|
||||
renderer_type[type]->terminate = TRUE;
|
||||
g_main_loop_quit( (GMainLoop *) loop);
|
||||
}
|
||||
break;
|
||||
@@ -878,8 +871,7 @@ static gboolean gstreamer_video_pipeline_bus_callback(GstBus *bus, GstMessage *m
|
||||
if (hls_video) {
|
||||
gst_bus_set_flushing(bus, TRUE);
|
||||
gst_element_set_state (renderer_type[type]->pipeline, GST_STATE_READY);
|
||||
renderer_type[type]->terminate = TRUE;
|
||||
g_main_loop_quit( (GMainLoop *) loop);
|
||||
renderer_type[type]->eos = TRUE;
|
||||
}
|
||||
break;
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
@@ -1021,20 +1013,6 @@ int video_renderer_choose_codec (bool video_is_jpeg, bool video_is_h265) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int video_reset_callback(void * loop) {
|
||||
if (video_terminate) {
|
||||
video_terminate = false;
|
||||
if (renderer->appsrc) {
|
||||
gst_app_src_end_of_stream (GST_APP_SRC(renderer->appsrc));
|
||||
}
|
||||
gboolean flushing = TRUE;
|
||||
gst_bus_set_flushing(renderer->bus, flushing);
|
||||
gst_element_set_state (renderer->pipeline, GST_STATE_NULL);
|
||||
g_main_loop_quit( (GMainLoop *) loop);
|
||||
}
|
||||
return (unsigned int) TRUE;
|
||||
}
|
||||
|
||||
bool video_get_playback_info(double *duration, double *position, float *rate, bool *buffer_empty, bool *buffer_full) {
|
||||
gint64 pos = 0;
|
||||
GstState state;
|
||||
@@ -1107,3 +1085,11 @@ unsigned int video_renderer_listen(void *loop, int id) {
|
||||
return (unsigned int) gst_bus_add_watch(renderer_type[id]->bus,(GstBusFunc)
|
||||
gstreamer_video_pipeline_bus_callback, (gpointer) loop);
|
||||
}
|
||||
|
||||
bool video_renderer_eos_watch() {
|
||||
if (hls_video && renderer->eos) {
|
||||
renderer->eos = FALSE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ typedef enum videoflip_e {
|
||||
|
||||
typedef struct video_renderer_s video_renderer_t;
|
||||
|
||||
void video_renderer_init (logger_t *logger, const char *server_name, videoflip_t videoflip[2], const char *parser, const char *rtp_pipeline,
|
||||
void video_renderer_init (logger_t *logger, const char *server_name, videoflip_t videoflip[2], const char *parser, const char *rtp_pipeline,
|
||||
const char *decoder, const char *converter, const char *videosink, const char *videosink_options,
|
||||
bool initial_fullscreen, bool video_sync, bool h265_support, bool coverart_support,
|
||||
guint playbin_version, const char *uri);
|
||||
void video_renderer_start (void *raop);
|
||||
void video_renderer_start ();
|
||||
void video_renderer_stop ();
|
||||
void video_renderer_pause ();
|
||||
void video_renderer_hls_ready ();
|
||||
@@ -60,6 +60,7 @@ void video_renderer_set_start(float position);
|
||||
void video_renderer_resume ();
|
||||
int video_renderer_cycle ();
|
||||
bool video_renderer_is_paused();
|
||||
bool video_renderer_eos_watch();
|
||||
uint64_t video_renderer_render_buffer (unsigned char* data, int *data_len, int *nal_count, uint64_t *ntp_time);
|
||||
void video_renderer_display_jpeg(const void *data, int *data_len);
|
||||
void video_renderer_flush ();
|
||||
@@ -70,7 +71,7 @@ bool waiting_for_x11_window();
|
||||
bool video_get_playback_info(double *duration, double *position, float *rate, bool *buffer_empty, bool *buffer_full);
|
||||
int video_renderer_choose_codec (bool video_is_jpeg, bool video_is_h265);
|
||||
unsigned int video_renderer_listen(void *loop, int id);
|
||||
unsigned int video_reset_callback(void *loop);
|
||||
bool video_renderer_eos_watch();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
19
uxplay.cpp
19
uxplay.cpp
@@ -178,6 +178,7 @@ static bool hls_support = false;
|
||||
static std::string lang = "";
|
||||
static std::string url = "";
|
||||
static guint gst_x11_window_id = 0;
|
||||
static guint video_eos_watch_id = 0;
|
||||
static guint progress_id = 0;
|
||||
static guint gst_hls_position_id = 0;
|
||||
static bool preserve_connections = false;
|
||||
@@ -633,6 +634,14 @@ static gboolean progress_callback (gpointer loop) {
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean video_eos_watch_callback (gpointer loop) {
|
||||
if (video_renderer_eos_watch()) {
|
||||
/* HLS video has sent EOS */
|
||||
LOGI("hls video has sent EOS");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define MAX_VIDEO_RENDERERS 3
|
||||
#define MAX_AUDIO_RENDERERS 2
|
||||
static void main_loop() {
|
||||
@@ -658,9 +667,11 @@ static void main_loop() {
|
||||
}
|
||||
/* renderer[0] : h264 video; followed by h265 video (optional) and jpeg (optional) */
|
||||
gst_x11_window_id = 0;
|
||||
video_eos_watch_id = 0;
|
||||
} else {
|
||||
/* hls video will be rendered: renderer[0] : hls */
|
||||
url.erase();
|
||||
video_eos_watch_id = g_timeout_add(100, (GSourceFunc) video_eos_watch_callback, (gpointer) loop);
|
||||
gst_x11_window_id = g_timeout_add(100, (GSourceFunc) x11_window_callback, (gpointer) loop);
|
||||
}
|
||||
g_assert(n_video_renderers <= MAX_VIDEO_RENDERERS);
|
||||
@@ -685,7 +696,6 @@ static void main_loop() {
|
||||
missed_feedback = 0;
|
||||
guint feedback_watch_id = g_timeout_add_seconds(1, (GSourceFunc) feedback_callback, (gpointer) loop);
|
||||
guint reset_watch_id = g_timeout_add(100, (GSourceFunc) reset_callback, (gpointer) loop);
|
||||
guint video_reset_watch_id = g_timeout_add(100, (GSourceFunc) video_reset_callback, (gpointer) loop);
|
||||
|
||||
#ifdef _WIN32
|
||||
gmainloop = loop;
|
||||
@@ -717,9 +727,10 @@ static void main_loop() {
|
||||
if (gst_audio_bus_watch_id[i] > 0) g_source_remove(gst_audio_bus_watch_id[i]);
|
||||
}
|
||||
if (gst_x11_window_id > 0) g_source_remove(gst_x11_window_id);
|
||||
if (video_eos_watch_id > 0) g_source_remove(video_eos_watch_id);
|
||||
if (reset_watch_id > 0) g_source_remove(reset_watch_id);
|
||||
if (progress_id > 0) g_source_remove(progress_id);
|
||||
if (video_reset_watch_id > 0) g_source_remove(video_reset_watch_id);
|
||||
if (video_eos_watch_id > 0) g_source_remove(video_eos_watch_id);
|
||||
if (feedback_watch_id > 0) g_source_remove(feedback_watch_id);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
@@ -2994,7 +3005,7 @@ int main (int argc, char *argv[]) {
|
||||
video_decoder.c_str(), video_converter.c_str(), videosink.c_str(),
|
||||
videosink_options.c_str(), fullscreen, video_sync, h265_support,
|
||||
render_coverart, playbin_version, NULL);
|
||||
video_renderer_start(NULL);
|
||||
video_renderer_start();
|
||||
#ifdef __OpenBSD__
|
||||
} else {
|
||||
if (pledge("stdio rpath wpath cpath inet unix prot_exec", NULL) == -1) {
|
||||
@@ -3096,7 +3107,7 @@ int main (int argc, char *argv[]) {
|
||||
video_decoder.c_str(), video_converter.c_str(), videosink.c_str(),
|
||||
videosink_options.c_str(), fullscreen, video_sync, h265_support,
|
||||
render_coverart, playbin_version, uri);
|
||||
video_renderer_start((void *) raop);
|
||||
video_renderer_start();
|
||||
}
|
||||
if (reset_httpd) {
|
||||
unsigned short port = raop_get_port(raop);
|
||||
|
||||
Reference in New Issue
Block a user