mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-12 02:15:31 +00:00
tests: simple-decoder: honour framerate from the bitstream.
Try to honour the framerate from the bitstream, or cap the playback to 60 fps by default.
This commit is contained in:
parent
7b4dadc8ae
commit
14242cda5d
2 changed files with 57 additions and 2 deletions
|
@ -105,8 +105,8 @@ test_textures_LDADD = libutils.la $(TEST_LIBS)
|
|||
simple_decoder_source_c = simple-decoder.c
|
||||
simple_decoder_source_h =
|
||||
simple_decoder_SOURCES = $(simple_decoder_source_c)
|
||||
simple_decoder_CFLAGS = $(TEST_CFLAGS)
|
||||
simple_decoder_LDADD = libutils.la $(TEST_LIBS)
|
||||
simple_decoder_CFLAGS = $(TEST_CFLAGS) $(GST_VIDEO_CFLAGS)
|
||||
simple_decoder_LDADD = libutils.la $(TEST_LIBS) $(GST_VIDEO_LIBS)
|
||||
|
||||
EXTRA_DIST = \
|
||||
test-subpicture-data.h \
|
||||
|
|
|
@ -74,6 +74,9 @@ typedef struct {
|
|||
GCond decoder_ready;
|
||||
GAsyncQueue *decoder_queue;
|
||||
GstVaapiCodec codec;
|
||||
guint fps_n;
|
||||
guint fps_d;
|
||||
guint32 frame_duration;
|
||||
guint surface_width;
|
||||
guint surface_height;
|
||||
GstVaapiWindow *window;
|
||||
|
@ -81,6 +84,7 @@ typedef struct {
|
|||
guint window_height;
|
||||
GThread *render_thread;
|
||||
volatile gboolean render_thread_cancel;
|
||||
GCond render_ready;
|
||||
GstBuffer *last_buffer;
|
||||
GError *error;
|
||||
AppEvent event;
|
||||
|
@ -193,6 +197,7 @@ decoder_thread(gpointer data)
|
|||
GstVaapiSurfaceProxy *proxy;
|
||||
GstVaapiVideoMeta *meta;
|
||||
GstBuffer *buffer;
|
||||
GstClockTime pts;
|
||||
gboolean got_surface;
|
||||
gint64 end_time;
|
||||
guint ofs;
|
||||
|
@ -205,6 +210,7 @@ decoder_thread(gpointer data)
|
|||
goto send_error; \
|
||||
} while (0)
|
||||
|
||||
pts = g_get_monotonic_time();
|
||||
ofs = 0;
|
||||
while (!app->decoder_thread_cancel) {
|
||||
if (G_UNLIKELY(ofs == app->file_size))
|
||||
|
@ -235,6 +241,9 @@ decoder_thread(gpointer data)
|
|||
buffer = gst_buffer_new();
|
||||
if (!buffer)
|
||||
SEND_ERROR("failed to allocate output buffer");
|
||||
GST_BUFFER_TIMESTAMP(buffer) = pts;
|
||||
GST_BUFFER_DURATION(buffer) = app->frame_duration;
|
||||
pts += app->frame_duration;
|
||||
gst_buffer_set_vaapi_video_meta(buffer, meta);
|
||||
gst_vaapi_video_meta_unref(meta);
|
||||
g_async_queue_push(app->decoder_queue, buffer);
|
||||
|
@ -272,6 +281,35 @@ send_error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
app_set_framerate(App *app, guint fps_n, guint fps_d)
|
||||
{
|
||||
if (!fps_n || !fps_d)
|
||||
return;
|
||||
|
||||
g_mutex_lock(&app->mutex);
|
||||
if (fps_n != app->fps_n || fps_d != app->fps_d) {
|
||||
app->fps_n = fps_n;
|
||||
app->fps_d = fps_d;
|
||||
app->frame_duration = gst_util_uint64_scale(
|
||||
GST_TIME_AS_USECONDS(GST_SECOND), fps_d, fps_n);
|
||||
}
|
||||
g_mutex_unlock(&app->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_decoder_caps(GObject *obj, GParamSpec *pspec, void *user_data)
|
||||
{
|
||||
App * const app = user_data;
|
||||
GstVideoCodecState *codec_state;
|
||||
|
||||
g_assert(app->decoder == GST_VAAPI_DECODER(obj));
|
||||
|
||||
codec_state = gst_vaapi_decoder_get_codec_state(app->decoder);
|
||||
app_set_framerate(app, codec_state->info.fps_n, codec_state->info.fps_d);
|
||||
gst_video_codec_state_unref(codec_state);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
start_decoder(App *app)
|
||||
{
|
||||
|
@ -312,6 +350,9 @@ start_decoder(App *app)
|
|||
if (!app->decoder)
|
||||
return FALSE;
|
||||
|
||||
g_signal_connect(G_OBJECT(app->decoder), "notify::caps",
|
||||
G_CALLBACK(handle_decoder_caps), app);
|
||||
|
||||
app->decoder_thread = g_thread_create(decoder_thread, app, TRUE, NULL);
|
||||
if (!app->decoder_thread)
|
||||
return FALSE;
|
||||
|
@ -346,6 +387,15 @@ ensure_window_size(App *app, GstVaapiSurface *surface)
|
|||
&app->window_width, &app->window_height);
|
||||
}
|
||||
|
||||
static inline void
|
||||
renderer_wait_until(App *app, GstClockTime pts)
|
||||
{
|
||||
g_mutex_lock(&app->mutex);
|
||||
do {
|
||||
} while (g_cond_wait_until(&app->render_ready, &app->mutex, pts));
|
||||
g_mutex_unlock(&app->mutex);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
renderer_process(App *app, GstBuffer *buffer)
|
||||
{
|
||||
|
@ -369,6 +419,8 @@ renderer_process(App *app, GstBuffer *buffer)
|
|||
|
||||
ensure_window_size(app, surface);
|
||||
|
||||
renderer_wait_until(app, GST_BUFFER_TIMESTAMP(buffer));
|
||||
|
||||
if (!gst_vaapi_window_put_surface(app->window, surface, NULL, NULL,
|
||||
GST_VAAPI_PICTURE_STRUCTURE_FRAME))
|
||||
SEND_ERROR("failed to render surface %" GST_VAAPI_ID_FORMAT,
|
||||
|
@ -459,6 +511,7 @@ app_free(App *app)
|
|||
}
|
||||
g_cond_clear(&app->decoder_ready);
|
||||
|
||||
g_cond_clear(&app->render_ready);
|
||||
g_cond_clear(&app->event_cond);
|
||||
g_mutex_clear(&app->mutex);
|
||||
g_slice_free(App, app);
|
||||
|
@ -476,7 +529,9 @@ app_new(void)
|
|||
g_mutex_init(&app->mutex);
|
||||
g_cond_init(&app->event_cond);
|
||||
g_cond_init(&app->decoder_ready);
|
||||
g_cond_init(&app->render_ready);
|
||||
|
||||
app_set_framerate(app, 60, 1);
|
||||
app->window_width = 640;
|
||||
app->window_height = 480;
|
||||
|
||||
|
|
Loading…
Reference in a new issue