mirror of
https://github.com/mpv-player/mpv
synced 2025-03-02 04:11:03 +00:00
vo_sixel: Buffer full output sequence
This allows the VO to write its output without interference from other processes or threads.
This commit is contained in:
parent
3ca31b6cf4
commit
fe21553637
@ -68,6 +68,7 @@ struct priv {
|
|||||||
sixel_dither_t *dither;
|
sixel_dither_t *dither;
|
||||||
sixel_dither_t *testdither;
|
sixel_dither_t *testdither;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
|
char *sixel_output_buf;
|
||||||
bool skip_frame_draw;
|
bool skip_frame_draw;
|
||||||
|
|
||||||
int left, top; // image origin cell (1 based)
|
int left, top; // image origin cell (1 based)
|
||||||
@ -324,24 +325,30 @@ static int update_sixel_swscaler(struct vo *vo, struct mp_image_params *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int sixel_write(char *data, int size, void *priv)
|
static inline int sixel_buffer(char *data, int size, void *priv) {
|
||||||
|
char **out = (char **)priv;
|
||||||
|
*out = talloc_strndup_append_buffer(*out, data, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int sixel_write(char *data, int size)
|
||||||
{
|
{
|
||||||
// On POSIX platforms, write() is the fastest method. It also is the only
|
// On POSIX platforms, write() is the fastest method. It also is the only
|
||||||
// one that—if implemented correctly—ensures atomic writes so mpv’s
|
// one that—if implemented correctly—ensures atomic writes so mpv’s
|
||||||
// output will not be interrupted by other processes or threads that write
|
// output will not be interrupted by other processes or threads that write
|
||||||
// to stdout, which would cause screen corruption.
|
// to stdout, which would cause screen corruption.
|
||||||
#if HAVE_POSIX
|
#if HAVE_POSIX
|
||||||
return write(fileno((FILE *)priv), data, size);
|
return write(fileno(stdout), data, size);
|
||||||
#else
|
#else
|
||||||
int ret = fwrite(data, 1, size, (FILE *)priv);
|
int ret = fwrite(data, 1, size, stdout);
|
||||||
fflush((FILE *)priv);
|
fflush(stdout);
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void write_str(char *s)
|
static inline void sixel_strwrite(char *s)
|
||||||
{
|
{
|
||||||
sixel_write(s, strlen(s), stdout);
|
sixel_write(s, strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reconfig(struct vo *vo, struct mp_image_params *params)
|
static int reconfig(struct vo *vo, struct mp_image_params *params)
|
||||||
@ -355,7 +362,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (priv->opts.draw_clear)
|
if (priv->opts.draw_clear)
|
||||||
write_str(TERM_ESC_CLEAR_SCREEN);
|
sixel_strwrite(TERM_ESC_CLEAR_SCREEN);
|
||||||
vo->want_redraw = true;
|
vo->want_redraw = true;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -385,7 +392,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
|||||||
update_sixel_swscaler(vo, vo->params);
|
update_sixel_swscaler(vo, vo->params);
|
||||||
|
|
||||||
if (priv->opts.draw_clear)
|
if (priv->opts.draw_clear)
|
||||||
write_str(TERM_ESC_CLEAR_SCREEN);
|
sixel_strwrite(TERM_ESC_CLEAR_SCREEN);
|
||||||
resized = true;
|
resized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,26 +464,26 @@ static void flip_page(struct vo *vo)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Go to the offset row and column, then display the image
|
// Go to the offset row and column, then display the image
|
||||||
char *cmd = talloc_asprintf(NULL, TERM_ESC_GOTO_YX,
|
priv->sixel_output_buf = talloc_asprintf(NULL, TERM_ESC_GOTO_YX,
|
||||||
priv->top, priv->left);
|
priv->top, priv->left);
|
||||||
write_str(cmd);
|
|
||||||
talloc_free(cmd);
|
|
||||||
sixel_encode(priv->buffer, priv->width, priv->height,
|
sixel_encode(priv->buffer, priv->width, priv->height,
|
||||||
depth, priv->dither, priv->output);
|
depth, priv->dither, priv->output);
|
||||||
|
sixel_write(priv->sixel_output_buf, ta_get_size(priv->sixel_output_buf));
|
||||||
|
|
||||||
|
talloc_free(priv->sixel_output_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int preinit(struct vo *vo)
|
static int preinit(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct priv *priv = vo->priv;
|
struct priv *priv = vo->priv;
|
||||||
SIXELSTATUS status = SIXEL_FALSE;
|
SIXELSTATUS status = SIXEL_FALSE;
|
||||||
FILE* sixel_output_file = stdout;
|
|
||||||
|
|
||||||
// Parse opts set by CLI or conf
|
// Parse opts set by CLI or conf
|
||||||
priv->sws = mp_sws_alloc(vo);
|
priv->sws = mp_sws_alloc(vo);
|
||||||
priv->sws->log = vo->log;
|
priv->sws->log = vo->log;
|
||||||
mp_sws_enable_cmdline_opts(priv->sws, vo->global);
|
mp_sws_enable_cmdline_opts(priv->sws, vo->global);
|
||||||
|
|
||||||
status = sixel_output_new(&priv->output, sixel_write, sixel_output_file, NULL);
|
status = sixel_output_new(&priv->output, sixel_buffer, &priv->sixel_output_buf, NULL);
|
||||||
if (SIXEL_FAILED(status)) {
|
if (SIXEL_FAILED(status)) {
|
||||||
MP_ERR(vo, "preinit: Failed to create output file: %s\n",
|
MP_ERR(vo, "preinit: Failed to create output file: %s\n",
|
||||||
sixel_helper_format_error(status));
|
sixel_helper_format_error(status));
|
||||||
@ -486,11 +493,12 @@ static int preinit(struct vo *vo)
|
|||||||
sixel_output_set_encode_policy(priv->output, SIXEL_ENCODEPOLICY_FAST);
|
sixel_output_set_encode_policy(priv->output, SIXEL_ENCODEPOLICY_FAST);
|
||||||
|
|
||||||
if (priv->opts.exit_clear)
|
if (priv->opts.exit_clear)
|
||||||
write_str(TERM_ESC_SAVE_SCREEN);
|
sixel_strwrite(TERM_ESC_SAVE_SCREEN);
|
||||||
write_str(TERM_ESC_HIDE_CURSOR);
|
|
||||||
|
sixel_strwrite(TERM_ESC_HIDE_CURSOR);
|
||||||
|
|
||||||
/* don't use private color registers for each frame. */
|
/* don't use private color registers for each frame. */
|
||||||
write_str(TERM_ESC_USE_GLOBAL_COLOR_REG);
|
sixel_strwrite(TERM_ESC_USE_GLOBAL_COLOR_REG);
|
||||||
|
|
||||||
priv->dither = NULL;
|
priv->dither = NULL;
|
||||||
|
|
||||||
@ -526,10 +534,10 @@ static void uninit(struct vo *vo)
|
|||||||
{
|
{
|
||||||
struct priv *priv = vo->priv;
|
struct priv *priv = vo->priv;
|
||||||
|
|
||||||
write_str(TERM_ESC_RESTORE_CURSOR);
|
sixel_strwrite(TERM_ESC_RESTORE_CURSOR);
|
||||||
|
|
||||||
if (priv->opts.exit_clear)
|
if (priv->opts.exit_clear)
|
||||||
write_str(TERM_ESC_RESTORE_SCREEN);
|
sixel_strwrite(TERM_ESC_RESTORE_SCREEN);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
if (priv->output) {
|
if (priv->output) {
|
||||||
|
Loading…
Reference in New Issue
Block a user