From 53894caccb2eac321cafd455cfd1035e7acde616 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 10 Apr 2021 04:02:38 -0400 Subject: [PATCH] add ncdirect_stream #1346 --- include/ncpp/Visual.hh | 2 +- include/notcurses/notcurses.h | 6 ++-- src/lib/direct.c | 56 +++++++++++++++++++++-------------- src/lib/internal.h | 2 +- src/lib/visual.c | 2 +- src/media/ffmpeg.c | 2 +- src/media/none.cpp | 2 +- src/media/oiio-indep.c | 2 +- 8 files changed, 43 insertions(+), 31 deletions(-) diff --git a/include/ncpp/Visual.hh b/include/ncpp/Visual.hh index a0397aed7..298fab650 100644 --- a/include/ncpp/Visual.hh +++ b/include/ncpp/Visual.hh @@ -71,7 +71,7 @@ namespace ncpp return error_guard (ncvisual_render (get_notcurses (), visual, vopts), nullptr); } - int stream (const ncvisual_options* vopts, float timescale, streamcb streamer, void *curry = nullptr) const NOEXCEPT_MAYBE + int stream (const ncvisual_options* vopts, float timescale, ncstreamcb streamer, void *curry = nullptr) const NOEXCEPT_MAYBE { return error_guard (ncvisual_stream (get_notcurses (), visual, timescale, streamer, vopts, curry), -1); } diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index a7b719c93..7fa259d68 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -2550,8 +2550,8 @@ API ALLOC char* ncvisual_subtitle(const struct ncvisual* ncv) // Called for each frame rendered from 'ncv'. If anything but 0 is returned, // the streaming operation ceases immediately, and that value is propagated out. // The recommended absolute display time target is passed in 'tspec'. -typedef int (*streamcb)(struct ncvisual*, struct ncvisual_options*, - const struct timespec*, void*); +typedef int (*ncstreamcb)(struct ncvisual*, struct ncvisual_options*, + const struct timespec*, void*); // Shut up and display my frames! Provide as an argument to ncvisual_stream(). // If you'd like subtitles to be decoded, provide an ncplane as the curry. If the @@ -2569,7 +2569,7 @@ API int ncvisual_simple_streamer(struct ncvisual* ncv, struct ncvisual_options* // 300FPS, and a 'timescale' of 10 will result in 3FPS. It is an error to // supply 'timescale' less than or equal to 0. API int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, - float timescale, streamcb streamer, + float timescale, ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry); // Blit a flat array 'data' of RGBA 32-bit values to the ncplane 'vopts->n', diff --git a/src/lib/direct.c b/src/lib/direct.c index 0b2962462..7a135b1ee 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -485,26 +485,20 @@ int ncdirect_raster_frame(ncdirect* n, ncdirectv* ncdv, ncalign_e align){ return r; } -ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, - ncblitter_e blitfxn, ncscale_e scale, - int ymax, int xmax){ +static ncdirectv* +ncdirect_render_visual(ncdirect* n, ncvisual* ncv, ncblitter_e blitfxn, + ncscale_e scale, int ymax, int xmax){ int dimy = ymax > 0 ? ymax : ncdirect_dim_y(n); int dimx = xmax > 0 ? xmax : ncdirect_dim_x(n); - struct ncvisual* ncv = ncvisual_from_file(file); - if(ncv == NULL){ - return NULL; - } //fprintf(stderr, "OUR DATA: %p rows/cols: %d/%d\n", ncv->data, ncv->rows, ncv->cols); int leny = ncv->rows; // we allow it to freely scroll int lenx = ncv->cols; if(leny == 0 || lenx == 0){ - ncvisual_destroy(ncv); return NULL; } //fprintf(stderr, "render %d/%d to %d+%d scaling: %d\n", ncv->rows, ncv->cols, leny, lenx, scale); const struct blitset* bset = rgba_blitter_low(&n->tcache, scale, true, blitfxn); if(!bset){ - ncvisual_destroy(ncv); return NULL; } int disprows, dispcols; @@ -542,7 +536,6 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, } struct ncplane* ncdv = ncplane_new_internal(NULL, NULL, &nopts); if(!ncdv){ - ncvisual_destroy(ncv); return NULL; } blitterargs bargs = {}; @@ -553,20 +546,29 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, int cols = lenx / bargs.u.pixel.celldimx + !!(lenx % bargs.u.pixel.celldimx); int rows = leny / bargs.u.pixel.celldimy + !!(leny % bargs.u.pixel.celldimy); if((bargs.u.pixel.spx = sprixel_alloc(ncdv, ncv, rows, cols)) == NULL){ - ncvisual_destroy(ncv); free_plane(ncdv); return NULL; } } if(ncvisual_blit(ncv, disprows, dispcols, ncdv, bset, leny, lenx, &bargs)){ - ncvisual_destroy(ncv); free_plane(ncdv); return NULL; } - ncvisual_destroy(ncv); return ncdv; } +ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file, + ncblitter_e blitfxn, ncscale_e scale, + int ymax, int xmax){ + struct ncvisual* ncv = ncvisual_from_file(file); + if(ncv == NULL){ + return NULL; + } + ncdirectv* v = ncdirect_render_visual(n, ncv, blitfxn, scale, ymax, xmax); + ncvisual_destroy(ncv); + return v; +} + int ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align, ncblitter_e blitfxn, ncscale_e scale){ ncdirectv* faken = ncdirect_render_frame(n, file, blitfxn, scale, -1, -1); @@ -1116,18 +1118,28 @@ int ncdirect_check_pixel_support(ncdirect* n){ return 0; } -int ncdirect_stream(ncdirect* nc, const char* filename, float timescale, - streamcb streamer, const struct ncvisual_options* vopts, - void* curry){ - (void)nc; - (void)timescale; - (void)streamer; - (void)vopts; - (void)curry; +int ncdirect_stream(ncdirect* n, const char* filename, ncstreamcb streamer, + struct ncvisual_options* vopts, void* curry){ + int y, x; + if(ncdirect_cursor_yx(n, &y, &x)){ + return -1; + } ncvisual* ncv = ncvisual_from_file(filename); if(ncv == NULL){ return -1; } - // FIXME + do{ + if(ncdirect_cursor_move_yx(n, y, x)){ + ncvisual_destroy(ncv); + return -1; + } + ncdirectv* v = ncdirect_render_visual(n, ncv, vopts->blitter, vopts->scaling, 0, 0); + if(v == NULL){ + ncvisual_destroy(ncv); + return -1; + } + streamer(ncv, vopts, NULL, curry); + }while(ncvisual_decode(ncv)); + ncvisual_destroy(ncv); return 0; } diff --git a/src/lib/internal.h b/src/lib/internal.h index de33ce291..d164f6b56 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -1448,7 +1448,7 @@ typedef struct ncvisual_implementation { int (*visual_decode)(struct ncvisual* nc); int (*visual_decode_loop)(struct ncvisual* nc); int (*visual_stream)(notcurses* nc, struct ncvisual* ncv, float timescale, - streamcb streamer, const struct ncvisual_options* vopts, void* curry); + ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry); char* (*visual_subtitle)(const struct ncvisual* ncv); int (*visual_resize)(struct ncvisual* ncv, int rows, int cols); void (*visual_destroy)(struct ncvisual* ncv); diff --git a/src/lib/visual.c b/src/lib/visual.c index 14e683089..0a5086aa0 100644 --- a/src/lib/visual.c +++ b/src/lib/visual.c @@ -847,7 +847,7 @@ int ncvisual_decode_loop(ncvisual* nc){ } int ncvisual_stream(notcurses* nc, ncvisual* ncv, float timescale, - streamcb streamer, const struct ncvisual_options* vopts, + ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry){ if(!visual_implementation){ return -1; diff --git a/src/media/ffmpeg.c b/src/media/ffmpeg.c index 914d0d4e4..c1c534544 100644 --- a/src/media/ffmpeg.c +++ b/src/media/ffmpeg.c @@ -377,7 +377,7 @@ err: // initial timestamp, and check each frame against the elapsed time to sync // up playback. int ffmpeg_stream(notcurses* nc, ncvisual* ncv, float timescale, - streamcb streamer, const struct ncvisual_options* vopts, + ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry){ int frame = 1; struct timespec begin; // time we started diff --git a/src/media/none.cpp b/src/media/none.cpp index 9e1d57dc6..35f328ef3 100644 --- a/src/media/none.cpp +++ b/src/media/none.cpp @@ -51,7 +51,7 @@ int none_blit(struct ncvisual* ncv, int rows, int cols, } int none_stream(notcurses* nc, ncvisual* ncv, float timescale, - streamcb streamer, const struct ncvisual_options* vopts, void* curry){ + ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry){ (void)nc; (void)ncv; (void)timescale; diff --git a/src/media/oiio-indep.c b/src/media/oiio-indep.c index d0c856f25..72f37f9d6 100644 --- a/src/media/oiio-indep.c +++ b/src/media/oiio-indep.c @@ -14,7 +14,7 @@ int oiio_blit_dispatch(struct ncplane* nc, const struct blitset* bset, } int oiio_stream(struct notcurses* nc, ncvisual* ncv, float timescale, - streamcb streamer, const struct ncvisual_options* vopts, + ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry){ (void)timescale; // FIXME int frame = 1;