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.
|
// 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:
|
||||||
|
@ -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***);**
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user