diff --git a/video/out/vo_tct.c b/video/out/vo_tct.c index 8859095fa3..5633a735b6 100644 --- a/video/out/vo_tct.c +++ b/video/out/vo_tct.c @@ -39,11 +39,13 @@ #define ALGO_PLAIN 1 #define ALGO_HALF_BLOCKS 2 -#define TERM_ESC_CLEAR_COLORS "\033[0m" -#define TERM_ESC_COLOR256_BG "\033[48;5" -#define TERM_ESC_COLOR256_FG "\033[38;5" -#define TERM_ESC_COLOR24BIT_BG "\033[48;2" -#define TERM_ESC_COLOR24BIT_FG "\033[38;2" +#define TERM_ESC_CLEAR_COLORS bstr0("\033[0m") +#define TERM_ESC_COLOR256_BG bstr0("\033[48;5") +#define TERM_ESC_COLOR256_FG bstr0("\033[38;5") +#define TERM_ESC_COLOR24BIT_BG bstr0("\033[48;2") +#define TERM_ESC_COLOR24BIT_FG bstr0("\033[38;2") + +#define UNICODE_LOWER_HALF_BLOCK bstr0("\xe2\x96\x84") #define DEFAULT_WIDTH 80 #define DEFAULT_HEIGHT 25 @@ -70,6 +72,7 @@ struct priv { struct mp_rect dst; struct mp_sws_context *sws; struct lut_item lut[256]; + bstr frame_buf; }; // Convert RGB24 to xterm-256 8-bit value @@ -101,37 +104,24 @@ static int rgb_to_x256(uint8_t r, uint8_t g, uint8_t b) return color_err <= gray_err ? 16 + color_index() : 232 + gray_index; } -static void print_seq3(struct lut_item *lut, const char* prefix, +static void print_seq3(bstr *frame, struct lut_item *lut, bstr prefix, uint8_t r, uint8_t g, uint8_t b) { -// The fwrite implementation is about 25% faster than the printf code -// (even if we use *.s with the lut values), however, -// on windows we need to use printf in order to translate escape sequences and -// UTF8 output for the console. -#ifndef _WIN32 - fputs(prefix, stdout); - fwrite(lut[r].str, lut[r].width, 1, stdout); - fwrite(lut[g].str, lut[g].width, 1, stdout); - fwrite(lut[b].str, lut[b].width, 1, stdout); - fputc('m', stdout); -#else - printf("%s;%d;%d;%dm", prefix, (int)r, (int)g, (int)b); -#endif + bstr_xappend(NULL, frame, prefix); + bstr_xappend(NULL, frame, (bstr){ lut[r].str, lut[r].width }); + bstr_xappend(NULL, frame, (bstr){ lut[g].str, lut[g].width }); + bstr_xappend(NULL, frame, (bstr){ lut[b].str, lut[b].width }); + bstr_xappend(NULL, frame, bstr0("m")); } -static void print_seq1(struct lut_item *lut, const char* prefix, uint8_t c) +static void print_seq1(bstr *frame, struct lut_item *lut, bstr prefix, uint8_t c) { -#ifndef _WIN32 - fputs(prefix, stdout); - fwrite(lut[c].str, lut[c].width, 1, stdout); - fputc('m', stdout); -#else - printf("%s;%dm", prefix, (int)c); -#endif + bstr_xappend(NULL, frame, prefix); + bstr_xappend(NULL, frame, (bstr){ lut[c].str, lut[c].width }); + bstr_xappend(NULL, frame, bstr0("m")); } - -static void write_plain( +static void write_plain(bstr *frame, const int dwidth, const int dheight, const int swidth, const int sheight, const unsigned char *source, const int source_stride, @@ -142,24 +132,23 @@ static void write_plain( const int ty = (dheight - sheight) / 2; for (int y = 0; y < sheight; y++) { const unsigned char *row = source + y * source_stride; - printf(TERM_ESC_GOTO_YX, ty + y, tx); + bstr_xappend_asprintf(NULL, frame, TERM_ESC_GOTO_YX, ty + y, tx); for (int x = 0; x < swidth; x++) { unsigned char b = *row++; unsigned char g = *row++; unsigned char r = *row++; if (term256) { - print_seq1(lut, TERM_ESC_COLOR256_BG, rgb_to_x256(r, g, b)); + print_seq1(frame, lut, TERM_ESC_COLOR256_BG, rgb_to_x256(r, g, b)); } else { - print_seq3(lut, TERM_ESC_COLOR24BIT_BG, r, g, b); + print_seq3(frame, lut, TERM_ESC_COLOR24BIT_BG, r, g, b); } - printf(" "); + bstr_xappend(NULL, frame, bstr0(" ")); } - printf(TERM_ESC_CLEAR_COLORS); + bstr_xappend(NULL, frame, TERM_ESC_CLEAR_COLORS); } - printf("\n"); } -static void write_half_blocks( +static void write_half_blocks(bstr *frame, const int dwidth, const int dheight, const int swidth, const int sheight, unsigned char *source, int source_stride, @@ -171,7 +160,7 @@ static void write_half_blocks( for (int y = 0; y < sheight * 2; y += 2) { const unsigned char *row_up = source + y * source_stride; const unsigned char *row_down = source + (y + 1) * source_stride; - printf(TERM_ESC_GOTO_YX, ty + y / 2, tx); + bstr_xappend_asprintf(NULL, frame, TERM_ESC_GOTO_YX, ty + y / 2, tx); for (int x = 0; x < swidth; x++) { unsigned char b_up = *row_up++; unsigned char g_up = *row_up++; @@ -180,17 +169,16 @@ static void write_half_blocks( unsigned char g_down = *row_down++; unsigned char r_down = *row_down++; if (term256) { - print_seq1(lut, TERM_ESC_COLOR256_BG, rgb_to_x256(r_up, g_up, b_up)); - print_seq1(lut, TERM_ESC_COLOR256_FG, rgb_to_x256(r_down, g_down, b_down)); + print_seq1(frame, lut, TERM_ESC_COLOR256_BG, rgb_to_x256(r_up, g_up, b_up)); + print_seq1(frame, lut, TERM_ESC_COLOR256_FG, rgb_to_x256(r_down, g_down, b_down)); } else { - print_seq3(lut, TERM_ESC_COLOR24BIT_BG, r_up, g_up, b_up); - print_seq3(lut, TERM_ESC_COLOR24BIT_FG, r_down, g_down, b_down); + print_seq3(frame, lut, TERM_ESC_COLOR24BIT_BG, r_up, g_up, b_up); + print_seq3(frame, lut, TERM_ESC_COLOR24BIT_FG, r_down, g_down, b_down); } - printf("\xe2\x96\x84"); // UTF8 bytes of U+2584 (lower half block) + bstr_xappend(NULL, frame, UNICODE_LOWER_HALF_BLOCK); } - printf(TERM_ESC_CLEAR_COLORS); + bstr_xappend(NULL, frame, TERM_ESC_CLEAR_COLORS); } - printf("\n"); } static void get_win_size(struct vo *vo, int *out_width, int *out_height) { @@ -262,17 +250,25 @@ static void flip_page(struct vo *vo) if (vo->dwidth != width || vo->dheight != height) reconfig(vo, vo->params); + p->frame_buf.len = 0; if (p->opts.algo == ALGO_PLAIN) { - write_plain( + write_plain(&p->frame_buf, vo->dwidth, vo->dheight, p->swidth, p->sheight, p->frame->planes[0], p->frame->stride[0], p->opts.term256, p->lut); } else { - write_half_blocks( + write_half_blocks(&p->frame_buf, vo->dwidth, vo->dheight, p->swidth, p->sheight, p->frame->planes[0], p->frame->stride[0], p->opts.term256, p->lut); } + + bstr_xappend(NULL, &p->frame_buf, bstr0("\n")); +#ifdef _WIN32 + printf("%.*s", BSTR_P(p->frame_buf)); +#else + fwrite(p->frame_buf.start, p->frame_buf.len, 1, stdout); +#endif fflush(stdout); } @@ -281,8 +277,8 @@ static void uninit(struct vo *vo) printf(TERM_ESC_RESTORE_CURSOR); printf(TERM_ESC_NORMAL_SCREEN); struct priv *p = vo->priv; - if (p->frame) - talloc_free(p->frame); + talloc_free(p->frame); + talloc_free(p->frame_buf.start); } static int preinit(struct vo *vo)