mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-26 16:06:52 +00:00
Implement throttling of seeks, only one seek per 500ms
This commit is contained in:
parent
76c883fb8b
commit
3123532841
1 changed files with 41 additions and 10 deletions
|
@ -24,12 +24,14 @@ GST_DEBUG_CATEGORY_STATIC (debug_category);
|
||||||
typedef struct _CustomData {
|
typedef struct _CustomData {
|
||||||
jobject app;
|
jobject app;
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
|
GMainContext *context;
|
||||||
GMainLoop *main_loop;
|
GMainLoop *main_loop;
|
||||||
ANativeWindow *native_window;
|
ANativeWindow *native_window;
|
||||||
GstState state, target_state;
|
GstState state, target_state;
|
||||||
gint64 position;
|
gint64 position;
|
||||||
gint64 duration;
|
gint64 duration;
|
||||||
gint64 desired_position;
|
gint64 desired_position;
|
||||||
|
GstClockTime last_seek_time;
|
||||||
gboolean initialized;
|
gboolean initialized;
|
||||||
gboolean is_live;
|
gboolean is_live;
|
||||||
} CustomData;
|
} CustomData;
|
||||||
|
@ -123,12 +125,41 @@ static gboolean refresh_ui (CustomData *data) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void execute_seek (gint64 desired_position, CustomData *data);
|
||||||
|
static gboolean
|
||||||
|
delayed_seek_cb (CustomData *data)
|
||||||
|
{
|
||||||
|
execute_seek (data->desired_position, data);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void execute_seek (gint64 desired_position, CustomData *data) {
|
static void execute_seek (gint64 desired_position, CustomData *data) {
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
gint64 diff;
|
||||||
|
|
||||||
|
if (desired_position == GST_CLOCK_TIME_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
diff = gst_util_get_timestamp () - data->last_seek_time;
|
||||||
|
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (data->last_seek_time) && diff < 500 * GST_MSECOND) {
|
||||||
|
GSource *timeout_source;
|
||||||
|
|
||||||
|
data->desired_position = desired_position;
|
||||||
|
timeout_source = g_timeout_source_new (diff / GST_MSECOND);
|
||||||
|
g_source_attach (timeout_source, data->context);
|
||||||
|
g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, data, NULL);
|
||||||
|
g_source_unref (timeout_source);
|
||||||
|
GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (desired_position), GST_TIME_ARGS (500 * GST_MSECOND - diff));
|
||||||
|
} else {
|
||||||
GST_DEBUG ("Setting position to %lld milliseconds", desired_position / GST_MSECOND);
|
GST_DEBUG ("Setting position to %lld milliseconds", desired_position / GST_MSECOND);
|
||||||
res = gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position);
|
res = gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position);
|
||||||
|
data->last_seek_time = gst_util_get_timestamp ();
|
||||||
|
data->desired_position = GST_CLOCK_TIME_NONE;
|
||||||
GST_DEBUG ("Seek returned %d", res);
|
GST_DEBUG ("Seek returned %d", res);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
|
static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
|
||||||
GError *err;
|
GError *err;
|
||||||
|
@ -226,12 +257,11 @@ static void *app_function (void *userdata) {
|
||||||
CustomData *data = (CustomData *)userdata;
|
CustomData *data = (CustomData *)userdata;
|
||||||
GSource *timeout_source;
|
GSource *timeout_source;
|
||||||
GSource *bus_source;
|
GSource *bus_source;
|
||||||
GMainContext *context;
|
|
||||||
|
|
||||||
GST_DEBUG ("Creating pipeline in CustomData at %p", data);
|
GST_DEBUG ("Creating pipeline in CustomData at %p", data);
|
||||||
|
|
||||||
/* create our own GLib Main Context, so we do not interfere with other libraries using GLib */
|
/* create our own GLib Main Context, so we do not interfere with other libraries using GLib */
|
||||||
context = g_main_context_new ();
|
data->context = g_main_context_new ();
|
||||||
|
|
||||||
data->pipeline = gst_element_factory_make ("playbin2", NULL);
|
data->pipeline = gst_element_factory_make ("playbin2", NULL);
|
||||||
|
|
||||||
|
@ -244,7 +274,7 @@ static void *app_function (void *userdata) {
|
||||||
bus = gst_element_get_bus (data->pipeline);
|
bus = gst_element_get_bus (data->pipeline);
|
||||||
bus_source = gst_bus_create_watch (bus);
|
bus_source = gst_bus_create_watch (bus);
|
||||||
g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL);
|
g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL);
|
||||||
g_source_attach (bus_source, context);
|
g_source_attach (bus_source, data->context);
|
||||||
g_source_unref (bus_source);
|
g_source_unref (bus_source);
|
||||||
g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data);
|
g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data);
|
||||||
g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data);
|
g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data);
|
||||||
|
@ -256,13 +286,13 @@ static void *app_function (void *userdata) {
|
||||||
|
|
||||||
/* Register a function that GLib will call 4 times per second */
|
/* Register a function that GLib will call 4 times per second */
|
||||||
timeout_source = g_timeout_source_new (250);
|
timeout_source = g_timeout_source_new (250);
|
||||||
g_source_attach (timeout_source, context);
|
g_source_attach (timeout_source, data->context);
|
||||||
g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL);
|
g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL);
|
||||||
g_source_unref (timeout_source);
|
g_source_unref (timeout_source);
|
||||||
|
|
||||||
/* Create a GLib Main Loop and set it to run */
|
/* Create a GLib Main Loop and set it to run */
|
||||||
GST_DEBUG ("Entering main loop... (CustomData:%p)", data);
|
GST_DEBUG ("Entering main loop... (CustomData:%p)", data);
|
||||||
data->main_loop = g_main_loop_new (context, FALSE);
|
data->main_loop = g_main_loop_new (data->context, FALSE);
|
||||||
check_initialization_complete (data);
|
check_initialization_complete (data);
|
||||||
g_main_loop_run (data->main_loop);
|
g_main_loop_run (data->main_loop);
|
||||||
GST_DEBUG ("Exited main loop");
|
GST_DEBUG ("Exited main loop");
|
||||||
|
@ -270,7 +300,7 @@ static void *app_function (void *userdata) {
|
||||||
data->main_loop = NULL;
|
data->main_loop = NULL;
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
g_main_context_unref (context);
|
g_main_context_unref (data->context);
|
||||||
data->target_state = GST_STATE_NULL;
|
data->target_state = GST_STATE_NULL;
|
||||||
gst_element_set_state (data->pipeline, GST_STATE_NULL);
|
gst_element_set_state (data->pipeline, GST_STATE_NULL);
|
||||||
gst_object_unref (data->pipeline);
|
gst_object_unref (data->pipeline);
|
||||||
|
@ -282,9 +312,10 @@ static void *app_function (void *userdata) {
|
||||||
* Java Bindings
|
* Java Bindings
|
||||||
*/
|
*/
|
||||||
void gst_native_init (JNIEnv* env, jobject thiz) {
|
void gst_native_init (JNIEnv* env, jobject thiz) {
|
||||||
CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData));
|
CustomData *data = g_new0 (CustomData, 1);
|
||||||
data->duration = GST_CLOCK_TIME_NONE;
|
data->duration = GST_CLOCK_TIME_NONE;
|
||||||
data->desired_position = GST_CLOCK_TIME_NONE;
|
data->desired_position = GST_CLOCK_TIME_NONE;
|
||||||
|
data->last_seek_time = GST_CLOCK_TIME_NONE;
|
||||||
SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data);
|
SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data);
|
||||||
GST_DEBUG ("Created CustomData at %p", data);
|
GST_DEBUG ("Created CustomData at %p", data);
|
||||||
data->app = (*env)->NewGlobalRef (env, thiz);
|
data->app = (*env)->NewGlobalRef (env, thiz);
|
||||||
|
|
Loading…
Reference in a new issue