mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
start handling type-1 DVB subtitles #1311
This commit is contained in:
parent
dbc060503c
commit
1448960cd5
8
USAGE.md
8
USAGE.md
@ -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.
|
||||
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
|
||||
// of the UTF8 text.
|
||||
char* ncvisual_subtitle(const struct ncvisual* ncv);
|
||||
// If a subtitle ought be displayed at this time, return a new plane (bound
|
||||
// to 'parent' containing the subtitle, which might be text or graphics
|
||||
// (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:
|
||||
|
@ -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***);**
|
||||
|
||||
**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***);**
|
||||
|
||||
|
@ -76,9 +76,9 @@ namespace ncpp
|
||||
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
|
||||
|
@ -2745,10 +2745,11 @@ ncvisualplane_create(struct ncplane* n, const struct ncplane_options* opts,
|
||||
return newn;
|
||||
}
|
||||
|
||||
// If a subtitle ought be displayed at this time, return a heap-allocated copy
|
||||
// of the UTF8 text.
|
||||
API ALLOC char* ncvisual_subtitle(const struct ncvisual* ncv)
|
||||
__attribute__ ((nonnull (1)));
|
||||
// If a subtitle ought be displayed at this time, return a new plane (bound
|
||||
// to 'parent' containing the subtitle, which might be text or graphics
|
||||
// (depending on the input format).
|
||||
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
|
||||
// the specified scaling method. Currently, this means:
|
||||
|
@ -1710,7 +1710,7 @@ typedef struct ncvisual_implementation {
|
||||
int (*visual_decode_loop)(struct ncvisual* nc);
|
||||
int (*visual_stream)(notcurses* nc, struct ncvisual* ncv, float timescale,
|
||||
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
|
||||
// do a persistent resize, changing the ncv itself
|
||||
int (*visual_resize)(struct ncvisual* ncv, int rows, int cols);
|
||||
|
@ -63,11 +63,11 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, float timescale,
|
||||
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){
|
||||
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,
|
||||
@ -1084,14 +1084,14 @@ int ncvisual_simple_streamer(ncvisual* ncv, struct ncvisual_options* vopts,
|
||||
}
|
||||
int ret = 0;
|
||||
if(curry){
|
||||
// FIXME improve this hrmmmmm
|
||||
ncplane* subncp = curry;
|
||||
char* subtitle = ncvisual_subtitle(ncv);
|
||||
if(subtitle){
|
||||
if(ncplane_putstr_yx(subncp, 0, 0, subtitle) < 0){
|
||||
ret = -1;
|
||||
}
|
||||
free(subtitle);
|
||||
if(subncp->blist){
|
||||
fprintf(stderr, "KILLING %p\n", subncp->blist);
|
||||
ncplane_destroy(subncp->blist);
|
||||
subncp->blist = NULL;
|
||||
}
|
||||
struct ncplane* subtitle = ncvisual_subtitle(subncp, ncv);
|
||||
}
|
||||
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, tspec, NULL);
|
||||
return ret;
|
||||
|
@ -115,15 +115,59 @@ deass(const char* ass){
|
||||
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){
|
||||
// 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];
|
||||
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){;
|
||||
return strdup(rect->text);
|
||||
return subtitle_plane_from_text(parent, rect->text);
|
||||
}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;
|
||||
|
@ -64,11 +64,6 @@ int oiio_stream(struct notcurses* nc, ncvisual* ncv, float timescale,
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* oiio_subtitle(const ncvisual* ncv) { // no support in OIIO
|
||||
(void)ncv;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int oiio_init(int logl __attribute__ ((unused))) {
|
||||
// FIXME set OIIO global attribute "debug" based on loglevel
|
||||
// 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_loop = oiio_decode_loop,
|
||||
.visual_stream = oiio_stream,
|
||||
.visual_subtitle = oiio_subtitle,
|
||||
.visual_resize = oiio_resize,
|
||||
.visual_destroy = oiio_destroy,
|
||||
.canopen_images = true,
|
||||
|
@ -44,7 +44,8 @@ struct marshal {
|
||||
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 {
|
||||
if(!marsh->subtitle_plane){
|
||||
int dimx, dimy;
|
||||
@ -72,9 +73,8 @@ auto handle_subtitle(char* subtitle, struct marshal* marsh,
|
||||
}else{
|
||||
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.
|
||||
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,
|
||||
notcurses_str_blitter(vopts->blitter));
|
||||
}
|
||||
char* subtitle = ncvisual_subtitle(ncv);
|
||||
if(subtitle){
|
||||
handle_subtitle(subtitle, marsh, vopts);
|
||||
}
|
||||
struct ncplane* subp = ncvisual_subtitle(*stdn, ncv);
|
||||
//if(subtitle){
|
||||
// handle_subtitle(subtitle, marsh, vopts);
|
||||
//}
|
||||
const int64_t h = ns / (60 * 60 * NANOSECS_IN_SEC);
|
||||
ns -= h * (60 * 60 * NANOSECS_IN_SEC);
|
||||
const int64_t m = ns / (60 * NANOSECS_IN_SEC);
|
||||
|
Loading…
x
Reference in New Issue
Block a user