start handling type-1 DVB subtitles #1311

This commit is contained in:
nick black 2021-07-27 09:49:15 -04:00 committed by nick black
parent dbc060503c
commit 1448960cd5
9 changed files with 77 additions and 36 deletions

View File

@ -3184,9 +3184,11 @@ int ncvisual_at_yx(const struct ncvisual* n, int y, int x, uint32_t* pixel);
// Set the specified pixel in the specified ncvisual. // Set the specified pixel in the specified ncvisual.
int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel); int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel);
// If a subtitle ought be displayed at this time, return a heap-allocated copy // If a subtitle ought be displayed at this time, return a new plane (bound
// of the UTF8 text. // to 'parent' containing the subtitle, which might be text or graphics
char* ncvisual_subtitle(const struct ncvisual* ncv); // (depending on the input format).
struct ncplane* ncvisual_subtitle(struct ncplane* parent,
const struct ncvisual* ncv);
``` ```
And finally, the `ncvisual` can be blitted to one or more `ncplane`s: And finally, the `ncvisual` can be blitted to one or more `ncplane`s:

View File

@ -90,7 +90,7 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
**int ncvisual_set_yx(const struct ncvisual* ***n***, int ***y***, int ***x***, uint32_t ***pixel***);** **int ncvisual_set_yx(const struct ncvisual* ***n***, int ***y***, int ***x***, uint32_t ***pixel***);**
**char* ncvisual_subtitle(const struct ncvisual* ***ncv***);** **struct ncplane* ncvisual_subtitle(struct ncplane* ***parent***, const struct ncvisual* ***ncv***);**
**int notcurses_lex_scalemode(const char* ***op***, ncscale_e* ***scaling***);** **int notcurses_lex_scalemode(const char* ***op***, ncscale_e* ***scaling***);**

View File

@ -76,9 +76,9 @@ namespace ncpp
return error_guard<int> (ncvisual_stream (get_notcurses (), visual, timescale, streamer, vopts, curry), -1); return error_guard<int> (ncvisual_stream (get_notcurses (), visual, timescale, streamer, vopts, curry), -1);
} }
char* subtitle () const noexcept ncplane* subtitle (Plane& p) const noexcept
{ {
return ncvisual_subtitle (visual); return ncvisual_subtitle (p, visual);
} }
bool rotate (double rads) const NOEXCEPT_MAYBE bool rotate (double rads) const NOEXCEPT_MAYBE

View File

@ -2745,10 +2745,11 @@ ncvisualplane_create(struct ncplane* n, const struct ncplane_options* opts,
return newn; return newn;
} }
// If a subtitle ought be displayed at this time, return a heap-allocated copy // If a subtitle ought be displayed at this time, return a new plane (bound
// of the UTF8 text. // to 'parent' containing the subtitle, which might be text or graphics
API ALLOC char* ncvisual_subtitle(const struct ncvisual* ncv) // (depending on the input format).
__attribute__ ((nonnull (1))); API ALLOC struct ncplane* ncvisual_subtitle(struct ncplane* parent, const struct ncvisual* ncv)
__attribute__ ((nonnull (1, 2)));
// Get the default *media* (not plot) blitter for this environment when using // Get the default *media* (not plot) blitter for this environment when using
// the specified scaling method. Currently, this means: // the specified scaling method. Currently, this means:

View File

@ -1710,7 +1710,7 @@ typedef struct ncvisual_implementation {
int (*visual_decode_loop)(struct ncvisual* nc); int (*visual_decode_loop)(struct ncvisual* nc);
int (*visual_stream)(notcurses* nc, struct ncvisual* ncv, float timescale, int (*visual_stream)(notcurses* nc, struct ncvisual* ncv, float timescale,
ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry); ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry);
char* (*visual_subtitle)(const struct ncvisual* ncv); struct ncplane* (*visual_subtitle)(struct ncplane* parent, const struct ncvisual* ncv);
int rowalign; // rowstride base, can be 0 for no padding int rowalign; // rowstride base, can be 0 for no padding
// do a persistent resize, changing the ncv itself // do a persistent resize, changing the ncv itself
int (*visual_resize)(struct ncvisual* ncv, int rows, int cols); int (*visual_resize)(struct ncvisual* ncv, int rows, int cols);

View File

@ -63,11 +63,11 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, float timescale,
return visual_implementation.visual_stream(nc, ncv, timescale, streamer, vopts, curry); return visual_implementation.visual_stream(nc, ncv, timescale, streamer, vopts, curry);
} }
char* ncvisual_subtitle(const ncvisual* ncv){ ncplane* ncvisual_subtitle(ncplane* parent, const ncvisual* ncv){
if(!visual_implementation.visual_subtitle){ if(!visual_implementation.visual_subtitle){
return NULL; return NULL;
} }
return visual_implementation.visual_subtitle(ncv); return visual_implementation.visual_subtitle(parent, ncv);
} }
int ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n, int ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n,
@ -1084,14 +1084,14 @@ int ncvisual_simple_streamer(ncvisual* ncv, struct ncvisual_options* vopts,
} }
int ret = 0; int ret = 0;
if(curry){ if(curry){
// FIXME improve this hrmmmmm
ncplane* subncp = curry; ncplane* subncp = curry;
char* subtitle = ncvisual_subtitle(ncv); if(subncp->blist){
if(subtitle){ fprintf(stderr, "KILLING %p\n", subncp->blist);
if(ncplane_putstr_yx(subncp, 0, 0, subtitle) < 0){ ncplane_destroy(subncp->blist);
ret = -1; subncp->blist = NULL;
}
free(subtitle);
} }
struct ncplane* subtitle = ncvisual_subtitle(subncp, ncv);
} }
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, tspec, NULL); clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, tspec, NULL);
return ret; return ret;

View File

@ -115,15 +115,59 @@ deass(const char* ass){
return dup; return dup;
} }
char* ffmpeg_subtitle(const ncvisual* ncv){ static struct ncplane*
subtitle_plane_from_text(ncplane* parent, const char* text){
if(parent == NULL){
//logerror("need a parent plane\n");
return NULL;
}
int width = ncstrwidth(text);
if(width <= 0){
//logwarn("couldn't extract subtitle from %s\n", text);
return NULL;
}
int rows = (width + ncplane_dim_x(parent) - 1) / ncplane_dim_x(parent);
struct ncplane_options nopts = {
.y = ncplane_dim_y(parent) - (rows + 1),
.rows = rows,
.cols = ncplane_dim_x(parent),
};
struct ncplane* n = ncplane_create(parent, &nopts);
if(n == NULL){
//logerror("error creating subtitle plane\n");
return NULL;
}
uint64_t channels = 0;
ncchannels_set_fg_alpha(&channels, NCALPHA_TRANSPARENT);
ncchannels_set_bg_alpha(&channels, NCALPHA_TRANSPARENT);
ncplane_set_base(n, "", 0, channels);
ncplane_puttext(n, 0, NCALIGN_LEFT, text, NULL);
return n;
}
struct ncplane* ffmpeg_subtitle(ncplane* parent, const ncvisual* ncv){
for(unsigned i = 0 ; i < ncv->details->subtitle.num_rects ; ++i){ for(unsigned i = 0 ; i < ncv->details->subtitle.num_rects ; ++i){
// it is possible that there are more than one subtitle rects present,
// but we only bother dealing with the first one we find FIXME?
const AVSubtitleRect* rect = ncv->details->subtitle.rects[i]; const AVSubtitleRect* rect = ncv->details->subtitle.rects[i];
if(rect->type == SUBTITLE_ASS){ if(rect->type == SUBTITLE_ASS){
return deass(rect->ass); char* ass = deass(rect->ass);
struct ncplane* n = NULL;
if(ass){
n = subtitle_plane_from_text(parent, ass);
}
free(ass);
return n;
}else if(rect->type == SUBTITLE_TEXT){; }else if(rect->type == SUBTITLE_TEXT){;
return strdup(rect->text); return subtitle_plane_from_text(parent, rect->text);
}else if(rect->type == SUBTITLE_BITMAP){ }else if(rect->type == SUBTITLE_BITMAP){
// FIXME // there are technically up to AV_NUM_DATA_POINTERS planes, but we
// only try to work with the first FIXME?
if(rect->linesize[0] != rect->w){
//logwarn("bitmap subtitle size %d != width %d\n", rect->linesize[0], rect->w);
return NULL;
}
// FIXME interpret the bytes of each line
} }
} }
return NULL; return NULL;

View File

@ -64,11 +64,6 @@ int oiio_stream(struct notcurses* nc, ncvisual* ncv, float timescale,
return -1; return -1;
} }
char* oiio_subtitle(const ncvisual* ncv) { // no support in OIIO
(void)ncv;
return NULL;
}
int oiio_init(int logl __attribute__ ((unused))) { int oiio_init(int logl __attribute__ ((unused))) {
// FIXME set OIIO global attribute "debug" based on loglevel // FIXME set OIIO global attribute "debug" based on loglevel
// FIXME check OIIO_VERSION_STRING components against linked openimageio_version() // FIXME check OIIO_VERSION_STRING components against linked openimageio_version()
@ -85,7 +80,6 @@ const ncvisual_implementation local_visual_implementation = {
.visual_decode = oiio_decode, .visual_decode = oiio_decode,
.visual_decode_loop = oiio_decode_loop, .visual_decode_loop = oiio_decode_loop,
.visual_stream = oiio_stream, .visual_stream = oiio_stream,
.visual_subtitle = oiio_subtitle,
.visual_resize = oiio_resize, .visual_resize = oiio_resize,
.visual_destroy = oiio_destroy, .visual_destroy = oiio_destroy,
.canopen_images = true, .canopen_images = true,

View File

@ -44,7 +44,8 @@ struct marshal {
ncblitter_e blitter; // can be changed while streaming, must propagate out ncblitter_e blitter; // can be changed while streaming, must propagate out
}; };
auto handle_subtitle(char* subtitle, struct marshal* marsh, /*
auto handle_subtitle(struct ncplane* subp, struct marshal* marsh,
const ncvisual_options* vopts) -> void { const ncvisual_options* vopts) -> void {
if(!marsh->subtitle_plane){ if(!marsh->subtitle_plane){
int dimx, dimy; int dimx, dimy;
@ -72,9 +73,8 @@ auto handle_subtitle(char* subtitle, struct marshal* marsh,
}else{ }else{
ncplane_erase(marsh->subtitle_plane); ncplane_erase(marsh->subtitle_plane);
} }
ncplane_printf_yx(marsh->subtitle_plane, 0, 0, "%s", subtitle);
free(subtitle);
} }
*/
// frame count is in the curry. original time is kept in n's userptr. // frame count is in the curry. original time is kept in n's userptr.
auto perframe(struct ncvisual* ncv, struct ncvisual_options* vopts, auto perframe(struct ncvisual* ncv, struct ncvisual_options* vopts,
@ -106,10 +106,10 @@ auto perframe(struct ncvisual* ncv, struct ncvisual_options* vopts,
stdn->printf(0, NCAlign::Left, "frame %06d (%s)", marsh->framecount, stdn->printf(0, NCAlign::Left, "frame %06d (%s)", marsh->framecount,
notcurses_str_blitter(vopts->blitter)); notcurses_str_blitter(vopts->blitter));
} }
char* subtitle = ncvisual_subtitle(ncv); struct ncplane* subp = ncvisual_subtitle(*stdn, ncv);
if(subtitle){ //if(subtitle){
handle_subtitle(subtitle, marsh, vopts); // handle_subtitle(subtitle, marsh, vopts);
} //}
const int64_t h = ns / (60 * 60 * NANOSECS_IN_SEC); const int64_t h = ns / (60 * 60 * NANOSECS_IN_SEC);
ns -= h * (60 * 60 * NANOSECS_IN_SEC); ns -= h * (60 * 60 * NANOSECS_IN_SEC);
const int64_t m = ns / (60 * NANOSECS_IN_SEC); const int64_t m = ns / (60 * NANOSECS_IN_SEC);