With synced playback, frames may be dropped if the OpenGL ES code does not output the decoded frames in time, thereby making sure the timestamps in the video aren't missed
Signed-off-by: Carlos Rafael Giani <d...@pseudoterminal.org> --- common.h | 8 ++++---- cube-video.c | 9 ++++++--- gst-decoder.c | 5 +++-- kmscube.c | 16 ++++++++++++---- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/common.h b/common.h index 639bd87..e10930e 100644 --- a/common.h +++ b/common.h @@ -102,17 +102,17 @@ const struct egl * init_cube_tex(const struct gbm *gbm, enum mode mode); #ifdef HAVE_GST struct decoder; -struct decoder * video_init(const struct egl *egl, const struct gbm *gbm, const char *filename); +struct decoder * video_init(const struct egl *egl, const struct gbm *gbm, const char *filename, int synced_playback); EGLImage video_frame(struct decoder *dec); void video_deinit(struct decoder *dec); -const struct egl * init_cube_video(const struct gbm *gbm, const char *video); +const struct egl * init_cube_video(const struct gbm *gbm, const char *video, int synced_playback); #else static inline const struct egl * -init_cube_video(const struct gbm *gbm, const char *video) +init_cube_video(const struct gbm *gbm, const char *video, int synced_playback) { - (void)gbm; (void)video; + (void)gbm; (void)video; (void)synced_playback; printf("no GStreamer support!\n"); return NULL; } diff --git a/cube-video.c b/cube-video.c index 6ce20da..32cce0a 100644 --- a/cube-video.c +++ b/cube-video.c @@ -49,6 +49,7 @@ struct { struct decoder *decoder; int filenames_count, idx; const char *filenames[32]; + int synced_playback; } gl; static const struct egl *egl = &gl.egl; @@ -230,7 +231,7 @@ static void draw_cube_video(unsigned i) glGenTextures(1, &gl.tex); video_deinit(gl.decoder); gl.idx = (gl.idx + 1) % gl.filenames_count; - gl.decoder = video_init(&gl.egl, gl.gbm, gl.filenames[gl.idx]); + gl.decoder = video_init(&gl.egl, gl.gbm, gl.filenames[gl.idx], gl.synced_playback); } glUseProgram(gl.blit_program); @@ -291,7 +292,7 @@ static void draw_cube_video(unsigned i) glDrawArrays(GL_TRIANGLE_STRIP, 20, 4); } -const struct egl * init_cube_video(const struct gbm *gbm, const char *filenames) +const struct egl * init_cube_video(const struct gbm *gbm, const char *filenames, int synced_playback) { char *fnames, *s; int ret, i = 0; @@ -305,6 +306,8 @@ const struct egl * init_cube_video(const struct gbm *gbm, const char *filenames) return NULL; } + gl.synced_playback = synced_playback; + fnames = strdup(filenames); while ((s = strstr(fnames, ","))) { gl.filenames[i] = fnames; @@ -315,7 +318,7 @@ const struct egl * init_cube_video(const struct gbm *gbm, const char *filenames) gl.filenames[i] = fnames; gl.filenames_count = ++i; - gl.decoder = video_init(&gl.egl, gbm, gl.filenames[gl.idx]); + gl.decoder = video_init(&gl.egl, gbm, gl.filenames[gl.idx], synced_playback); if (!gl.decoder) { printf("cannot create video decoder\n"); return NULL; diff --git a/gst-decoder.c b/gst-decoder.c index deffad5..6cdf9c4 100644 --- a/gst-decoder.c +++ b/gst-decoder.c @@ -253,7 +253,7 @@ appsink_query_cb(GstPad *pad G_GNUC_UNUSED, GstPadProbeInfo *info, } struct decoder * -video_init(const struct egl *egl, const struct gbm *gbm, const char *filename) +video_init(const struct egl *egl, const struct gbm *gbm, const char *filename, int synced_playback) { struct decoder *dec; GstElement *src, *decodebin; @@ -267,7 +267,7 @@ video_init(const struct egl *egl, const struct gbm *gbm, const char *filename) /* Setup pipeline: */ static const char *pipeline = - "filesrc name=\"src\" ! decodebin name=\"decode\" ! video/x-raw ! appsink sync=false name=\"sink\""; + "filesrc name=\"src\" ! decodebin name=\"decode\" ! video/x-raw ! appsink name=\"sink\""; dec->pipeline = gst_parse_launch(pipeline, NULL); dec->sink = gst_bin_get_by_name(GST_BIN(dec->pipeline), "sink"); @@ -294,6 +294,7 @@ video_init(const struct egl *egl, const struct gbm *gbm, const char *filename) * vsync and quickly chew up 100's of MB of buffers: */ g_object_set(G_OBJECT(dec->sink), "max-buffers", 2, NULL); + g_object_set(G_OBJECT(dec->sink), "sync", (gboolean)(!!synced_playback), NULL); gst_pad_add_probe(gst_element_get_static_pad(dec->sink, "sink"), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, diff --git a/kmscube.c b/kmscube.c index 3a2c4dd..486a558 100644 --- a/kmscube.c +++ b/kmscube.c @@ -43,7 +43,7 @@ static const struct egl *egl; static const struct gbm *gbm; static const struct drm *drm; -static const char *shortopts = "AD:M:m:V:"; +static const char *shortopts = "AD:M:m:V:S"; static const struct option longopts[] = { {"atomic", no_argument, 0, 'A'}, @@ -51,12 +51,13 @@ static const struct option longopts[] = { {"mode", required_argument, 0, 'M'}, {"modifier", required_argument, 0, 'm'}, {"video", required_argument, 0, 'V'}, + {"synced-playback", no_argument, 0, 'S'}, {0, 0, 0, 0} }; static void usage(const char *name) { - printf("Usage: %s [-ADMmV]\n" + printf("Usage: %s [-ADMmVS]\n" "\n" "options:\n" " -A, --atomic use atomic modesetting and fencing\n" @@ -67,7 +68,10 @@ static void usage(const char *name) " nv12-2img - yuv textured (color conversion in shader)\n" " nv12-1img - yuv textured (single nv12 texture)\n" " -m, --modifier=MODIFIER hardcode the selected modifier\n" - " -V, --video=FILE video textured cube\n", + " -V, --video=FILE video textured cube\n" + " -S, --synced-playback make sure playback stays in sync\n" + " with the timestamps in the video;\n" + " this drops frames if necessary\n", name); } @@ -78,6 +82,7 @@ int main(int argc, char *argv[]) enum mode mode = SMOOTH; uint64_t modifier = DRM_FORMAT_MOD_INVALID; int atomic = 0; + int synced_playback = 0; int opt; #ifdef HAVE_GST @@ -115,6 +120,9 @@ int main(int argc, char *argv[]) mode = VIDEO; video = optarg; break; + case 'S': + synced_playback = 1; + break; default: usage(argv[0]); return -1; @@ -140,7 +148,7 @@ int main(int argc, char *argv[]) if (mode == SMOOTH) egl = init_cube_smooth(gbm); else if (mode == VIDEO) - egl = init_cube_video(gbm, video); + egl = init_cube_video(gbm, video, synced_playback); else egl = init_cube_tex(gbm, mode); -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev