diff options
author | David I. Lehn <dlehn@users.sourceforge.net> | 2002-12-19 21:34:56 +0000 |
---|---|---|
committer | David I. Lehn <dlehn@users.sourceforge.net> | 2002-12-19 21:34:56 +0000 |
commit | 61898506c8fe0bf85170ab290bf3aecb2c0a81b0 (patch) | |
tree | a35814d30baa44a104addadcd9ec14c3eb4fd749 /gst/vbidec/vbiscreen.c | |
parent | 08d0c89de597cd1cd287bd34fea49453a3f24aa9 (diff) | |
download | gst-plugins-bad-61898506c8fe0bf85170ab290bf3aecb2c0a81b0.tar.gz gst-plugins-bad-61898506c8fe0bf85170ab290bf3aecb2c0a81b0.tar.bz2 gst-plugins-bad-61898506c8fe0bf85170ab290bf3aecb2c0a81b0.zip |
initial checkin of work-in-progress vbidec plugin for closed caption support
Original commit message from CVS:
initial checkin of work-in-progress vbidec plugin for closed caption support
Diffstat (limited to 'gst/vbidec/vbiscreen.c')
-rw-r--r-- | gst/vbidec/vbiscreen.c | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/gst/vbidec/vbiscreen.c b/gst/vbidec/vbiscreen.c new file mode 100644 index 00000000..1143e06b --- /dev/null +++ b/gst/vbidec/vbiscreen.c @@ -0,0 +1,730 @@ +/** + * Copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>. + * Copyright (c) 2002 Doug Bell <drbell@users.sourceforge.net>. + * + * Modified and adapted to GStreamer by + * David I. Lehn <dlehn@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +/*#include "osdtools.h"*/ +/*#include "speedy.h"*/ +#include "vbiscreen.h" +#include "gstvbidec.h" + +#define ROLL_2 6 +#define ROLL_3 7 +#define ROLL_4 8 +#define POP_UP 9 +#define PAINT_ON 10 + + +#define NUM_LINES 15 +#define ROWS 15 +#define COLS 32 +#define FONT_SIZE 20 + +typedef struct osd_string_s osd_string_t; +struct osd_string_s { + int width; + int height; + int r, g, b; + int visible; + GstVBIDec *vbidec; +}; + +osd_string_t *osd_string_new(char *c, int s, int w, int h, int a, void *user_data) { + osd_string_t *os; + os = (osd_string_t *)malloc(sizeof(osd_string_t)); + if (!os) + return NULL; + os->width = 0; + os->height = 0; + os->r = os->g = os->b = 0; + os->visible = 1; + os->vbidec = (GstVBIDec *)user_data; + return os; +} +void osd_string_show_text(osd_string_t *os, char *s, int len ) { + /* FIXME: just print data when it gets here */ + if (len > 0) { + gst_vbidec_show_text(os->vbidec, s, len); + } +} +int osd_string_get_height(osd_string_t *os) { + return os->height; +} +int osd_string_get_width(osd_string_t *os) { + return os->width; +} +void osd_string_delete(osd_string_t *os) { + free(os); +} +void osd_string_set_colour_rgb(osd_string_t *os, int r, int g, int b) { + os->r = r; + os->g = g; + os->b = b; +} +void blit_colour_packed422_scanline( unsigned char *d, int w, int luma, int cb, int cr) { +} +int osd_string_visible(osd_string_t *os) { + return os->visible; +} +void osd_string_composite_packed422_scanline(osd_string_t *os, unsigned char *a, unsigned char *b, int w, int x, int y) { +} + +struct vbiscreen_s { + + osd_string_t *line[ ROWS ]; + + char buffers[ ROWS * COLS * 2 ]; + char text[ 2 * ROWS * COLS ]; + char hiddenbuf[ COLS ]; + char paintbuf[ ROWS * COLS ]; + + unsigned int fgcolour; + unsigned int bgcolour; + int bg_luma, bg_cb, bg_cr; + + int frame_width; + int frame_height; + int frame_aspect; + + int x, y; /* where to draw console */ + int width, height; /* the size box we have to draw in */ + int rowheight, charwidth; + + int curx, cury; /* cursor position */ + int rows, cols; /* 32 cols 15 rows */ + int captions, style; /* CC (1) or Text (0), RU2 RU3 RU4 POP_UP PAINT_ON */ + int first_line; /* where to start drawing */ + int curbuffer; + int top_of_screen; /* a pointer into line[] */ + int indent; + int got_eoc; + int scroll; + + char *fontfile; + int fontsize; + int verbose; + + void *user_data; +}; + +vbiscreen_t *vbiscreen_new( int video_width, int video_height, + double video_aspect, int verbose, void *user_data ) +{ + int i=0, fontsize = FONT_SIZE; + vbiscreen_t *vs = (vbiscreen_t *)malloc(sizeof(struct vbiscreen_s)); + + if( !vs ) { + return NULL; + } + + vs->verbose = verbose; + vs->x = 0; + vs->y = 0; + vs->frame_width = video_width; + vs->frame_height = video_height; + vs->frame_aspect = video_aspect; + vs->curx = 0; + vs->cury = 0; + vs->fgcolour = 0xFFFFFFFFU; /* white */ + vs->bgcolour = 0xFF000000U; /* black */ + vs->bg_luma = 16; + vs->bg_cb = 128; + vs->bg_cr = 128; + vs->rows = ROWS; + vs->cols = COLS; + /*vs->fontfile = DATADIR "/FreeMonoBold.ttf";*/ + vs->fontfile = NULL; + vs->fontsize = fontsize; + vs->width = video_width; + vs->height = video_height; + vs->first_line = 0; + vs->captions = 0; + vs->style = 0; + vs->curbuffer = 0; + vs->top_of_screen = 0; + vs->indent = 0; + memset( vs->buffers, 0, 2 * COLS * ROWS ); + memset( vs->hiddenbuf, 0, COLS ); + memset( vs->paintbuf, 0, ROWS * COLS ); + vs->scroll = 0; + + vs->user_data = user_data; + + vs->line[0] = osd_string_new( vs->fontfile, fontsize, video_width, + video_height, + video_aspect, + user_data); + + if( !vs->line[0] ) { + vs->fontfile = "./FreeMonoBold.ttf"; + + vs->line[0] = osd_string_new( vs->fontfile, fontsize, + video_width, + video_height, + video_aspect, + user_data); + } + + if( !vs->line[0] ) { + fprintf( stderr, "vbiscreen: Could not find my font (%s)!\n", + vs->fontfile ); + vbiscreen_delete( vs ); + return NULL; + } + + osd_string_show_text( vs->line[ 0 ], "W", 0 ); + vs->rowheight = osd_string_get_height( vs->line[ 0 ] ); + vs->charwidth = osd_string_get_width( vs->line[ 0 ] ); + osd_string_delete( vs->line[ 0 ] ); + + for( i = 0; i < ROWS; i++ ) { + vs->line[ i ] = osd_string_new( vs->fontfile, fontsize, + video_width, video_height, + video_aspect, + user_data); + if( !vs->line[ i ] ) { + fprintf( stderr, "vbiscreen: Could not allocate a line.\n" ); + vbiscreen_delete( vs ); + return NULL; + } + osd_string_set_colour_rgb( vs->line[ i ], + (vs->fgcolour & 0xff0000) >> 16, + (vs->fgcolour & 0xff00) >> 8, + (vs->fgcolour & 0xff) ); + osd_string_show_text( vs->line[ i ], " ", 0 ); + } + memset( vs->text, 0, 2 * ROWS * COLS ); + return vs; +} + +void blank_screen( vbiscreen_t *vs ) +{ + int i; + + if( vs->verbose ) fprintf( stderr, "in blank\n"); + for( i = 0; i < ROWS; i++ ) { + osd_string_show_text( vs->line[ i ], " ", 0 ); + } +} + +void clear_screen( vbiscreen_t *vs ) +{ + int base, i; + if( !vs ) return; + + base = vs->top_of_screen * COLS; + for( i = 0; i < ROWS * COLS; i++ ) { + vs->text[ base ] = 0; + base++; + base %= 2 * ROWS * COLS; + } + blank_screen( vs ); +} + +void clear_hidden_roll( vbiscreen_t *vs ) +{ + if( !vs ) return; + memset( vs->hiddenbuf, 0, COLS ); +} + +void clear_hidden_pop( vbiscreen_t *vs ) +{ + if( !vs ) return; + memset( vs->buffers + vs->curbuffer * COLS * ROWS , 0, COLS * ROWS ); +} + +void clear_hidden_paint( vbiscreen_t *vs ) +{ + if( !vs ) return; + memset( vs->paintbuf , 0, COLS * ROWS ); +} + +void clear_displayed_pop( vbiscreen_t *vs ) +{ + if( !vs ) return; + memset( vs->buffers + ( vs->curbuffer ^ 1 ) * COLS * ROWS , 0, COLS * ROWS ); +} + +void vbiscreen_dump_screen_text( vbiscreen_t *vs ) +{ + int i, offset; + + if( !vs ) return; + offset = vs->top_of_screen * COLS; + + fprintf( stderr, "\n 0123456789abcdefghij012345678901" ); + for( i = 0; i < ROWS * COLS; i++ ) { + if( !(i % COLS) ) + fprintf( stderr, "\n%.2d ", i / COLS ); + fprintf( stderr, "%c", vs->text[ offset ] ? vs->text[ offset ] : ' ' ); + offset++; + offset %= 2 * ROWS * COLS; + } + fprintf( stderr, "\n 0123456789abcdefghij012345678901\n " ); + for( i = 0; i < COLS; i++ ) { + fprintf( stderr, "%c", vs->text[ offset ] ? vs->text[ offset ] : ' ' ); + offset++; + offset %= 2 * ROWS * COLS; + } + fprintf( stderr, "\n 0123456789abcdefghij012345678901\n" ); +} + +int update_row_x( vbiscreen_t *vs, int row ) +{ + char text[ COLS + 1 ]; + int i, j, haschars = 0, base; + + if( !vs ) return 0; + + text[ COLS ] = 0; + base = ( ( vs->top_of_screen + row ) % ( 2 * ROWS ) ) * COLS; + for( j = 0, i = base; i < base + COLS; i++, j++ ) { + if( vs->text[ i ] ) { + text[ j ] = vs->text[ i ]; + haschars = 1; + } else { + text[ j ] = ' '; + } + } + + osd_string_set_colour_rgb( vs->line[ row ], + ( vs->fgcolour & 0xff0000 ) >> 16, + ( vs->fgcolour & 0xff00 ) >> 8, + ( vs->fgcolour & 0xff ) ); + if( !haschars ) + osd_string_show_text( vs->line[ row ], " ", 0 ); + else + osd_string_show_text( vs->line[ row ], text, 51 ); + + return haschars; +} + +void update_row( vbiscreen_t *vs ) +{ + if( !vs ) return; + + update_row_x( vs, vs->cury ); + //vbiscreen_dump_screen_text( vs ); +} + +void update_all_rows( vbiscreen_t *vs ) +{ + int row = 0; + + if( !vs ) return; + + for( row = 0; row < ROWS; row++ ) { + update_row_x( vs, row ); + } + //vbiscreen_dump_screen_text( vs ); +} + +void vbiscreen_delete( vbiscreen_t *vs ) +{ + free( vs ); +} + +void copy_row_to_screen( vbiscreen_t *vs, char *row ) +{ + int base, i, j; + + base = ( ( vs->top_of_screen + vs->cury ) % ( 2 * ROWS ) ) * COLS; + for( j = 0, i = base; + i < base + COLS; + j++, i++ ) { + vs->text[ i ] = row[ j ]; + } + update_row( vs ); +} + +void scroll_screen( vbiscreen_t *vs ) +{ + int start_row; + + if( !vs || !vs->captions || !vs->style || vs->style > ROLL_4 ) + return; + + start_row = ( vs->first_line + vs->top_of_screen ) % ( 2 * ROWS ); + if( vs->verbose ) + fprintf ( stderr, "start row : %d first line %d\n ", start_row, + vs->first_line ); + + /* zero out top row */ + memset( (char *)( vs->text + start_row * COLS ), 0, COLS ); + vs->top_of_screen = ( vs->top_of_screen + 1 ) % ( 2 * ROWS ); + vs->curx = vs->indent; + update_all_rows( vs ); + copy_row_to_screen( vs, vs->hiddenbuf ); + clear_hidden_roll( vs ); + vs->scroll = 26; +} + +void vbiscreen_new_caption( vbiscreen_t *vs, int indent, int ital, + unsigned int colour, int row ) +{ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "indent: %d, ital: %d, colour: 0x%x, row: %d\n", indent, ital, colour, row ); + + if( 0 && vs->captions && vs->style <= ROLL_4 && vs->style ) { + if( row != vs->cury+1 ) { + vs->cury = row - 1; + clear_hidden_roll( vs ); + } else { +// scroll_screen( vs ); + } + } + + if( vs->style > ROLL_4 ) { + vs->cury = ( ( row > 0 ) ? row - 1 : 0 ); + } + + vs->fgcolour = colour; + vs->indent = indent; + vs->curx = indent; +} + +void vbiscreen_set_mode( vbiscreen_t *vs, int caption, int style ) +{ + if( !vs ) return; + if( vs->verbose ) + fprintf( stderr, "in set mode\n"); + + if( vs->verbose ) { + fprintf( stderr, "Caption: %d ", caption ); + switch( style ) { + case ROLL_2: + fprintf( stderr, "ROLL 2\n"); + break; + case ROLL_3: + fprintf( stderr, "ROLL 3\n" ); + break; + case ROLL_4: + fprintf( stderr, "ROLL 4\n" ); + break; + case POP_UP: + fprintf( stderr, "POP UP\n" ); + break; + case PAINT_ON: + fprintf( stderr, "PAINT ON\n" ); + break; + default: + break; + } + } + if( !caption ) { + /* text mode */ + vs->cury = 0; + } else { + /* captioning mode */ + /* styles: ru2 ru3 ru4 pop paint + */ + if( style != POP_UP && vs->style == POP_UP && !vs->got_eoc ) { + /* stupid that sometimes they dont send a EOC */ + vbiscreen_end_of_caption( vs ); + } + + switch( style ) { + case ROLL_2: + case ROLL_3: + case ROLL_4: + if( vs->style == style ) { + return; + } + vs->first_line = ROWS - (style - 4); + + if( vs->verbose ) + fprintf( stderr, "first_line %d\n", vs->first_line ); + + vs->cury = ROWS - 1; + break; + case POP_UP: + vs->got_eoc = 0; + break; + case PAINT_ON: + break; + } + } + + vs->captions = caption; + vs->style = style; +} + +void vbiscreen_tab( vbiscreen_t *vs, int cols ) +{ + if( !vs ) return; + if( cols < 0 || cols > 3 ) return; + vs->curx += cols; + if( vs->curx > 31 ) vs->curx = 31; +} + +void vbiscreen_set_colour( vbiscreen_t *vs, unsigned int col ) +{ + if( !vs ) return; + vs->fgcolour = col; +} + +void vbiscreen_clear_current_cell( vbiscreen_t *vs ) +{ + vs->text[ ( ( vs->top_of_screen + vs->cury ) % ( 2 * ROWS ) ) * COLS + + vs->curx + vs->indent ] = 0; +} + +void vbiscreen_set_current_cell( vbiscreen_t *vs, char text ) +{ + int base; + if( !vs ) return; + base = ( ( vs->top_of_screen + vs->cury ) % ( 2 * ROWS ) ) * COLS; + if( isprint( text ) ) + vs->text[ base + vs->curx + vs->indent ] = text; + else + vs->text[ base + vs->curx + vs->indent ] = ' '; +} + +void vbiscreen_delete_to_end( vbiscreen_t *vs ) +{ + int i; + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in del to end\n"); + for( i = vs->curx; i < COLS; i++ ) { + vbiscreen_clear_current_cell( vs ); + vs->curx++; + } + vs->curx = COLS-1; /* is this right ? */ + if( vs->captions && vs->style && vs->style != POP_UP ) + update_row( vs ); +} + +void vbiscreen_backspace( vbiscreen_t *vs ) +{ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in backspace\n"); + if( !vs->curx ) return; + vs->curx--; + vbiscreen_clear_current_cell( vs ); + update_row( vs ); +} + +void vbiscreen_erase_displayed( vbiscreen_t *vs ) +{ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in erase disp\n"); + + if( vs->captions && vs->style && vs->style <= ROLL_4 ) { + clear_hidden_roll( vs ); + } + + clear_displayed_pop( vs ); + clear_screen( vs ); +} + +void vbiscreen_erase_non_displayed( vbiscreen_t *vs ) +{ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in erase non disp\n"); + + if( vs->captions && vs->style == POP_UP ) { + memset( vs->buffers + vs->curbuffer * COLS * ROWS + vs->cury * COLS, 0, COLS ); +// clear_hidden_pop( vs ); + } else if( vs->captions && vs->style && vs->style <= ROLL_4 ) { + clear_hidden_roll( vs ); + } +} + +void vbiscreen_carriage_return( vbiscreen_t *vs ) +{ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in CR\n"); + if( vs->style != POP_UP) { + /* not sure if this is right for text mode */ + /* in text mode, perhaps a CR on last row clears screen and goes + * to (0,0) */ + scroll_screen( vs ); + } + + /* keep cursor on bottom for rollup */ + if( vs->captions && vs->style && vs->style <= ROLL_4 ) + vs->cury--; + + vs->cury++; + vs->curx = 0; +} + +void copy_buf_to_screen( vbiscreen_t *vs, char *buf ) +{ + int base, i, j; + if( !vs ) return; + + base = vs->top_of_screen * COLS; + for( j = 0, i = 0; i < ROWS * COLS; i++, j++ ) { + vs->text[ base ] = buf[ j ]; + base++; + base %= 2 * ROWS * COLS; + } + update_all_rows( vs ); +} + +void vbiscreen_end_of_caption( vbiscreen_t *vs ) +{ + /*int i;*/ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in end of caption\n"); + + if( vs->style == PAINT_ON ) { + copy_buf_to_screen( vs, vs->paintbuf ); + clear_hidden_paint( vs ); + } else if( vs->style == POP_UP ) { + copy_buf_to_screen( vs, vs->buffers + vs->curbuffer * COLS * ROWS ); + vs->curbuffer ^= 1; + } + + /* to be safe? */ + vs->curx = 0; + vs->cury = ROWS - 1; + vs->got_eoc = 1; +} + +void vbiscreen_print( vbiscreen_t *vs, char c1, char c2 ) +{ + if( !vs ) return; + if( vs->verbose ) fprintf( stderr, "in print (%d, %d)[%c %c]\n", vs->curx, vs->cury, c1, c2); + if( vs->captions && vs->style == POP_UP ) { + /* this all gets displayed at another time */ + if( vs->curx != COLS-1 ) { + *(vs->buffers + vs->curx + vs->curbuffer * ROWS * COLS + vs->cury * COLS ) = c1; + vs->curx++; + } + + if( vs->curx != COLS-1 && c2 ) { + *(vs->buffers + vs->curx + vs->curbuffer * ROWS * COLS + vs->cury * COLS ) = c2; + vs->curx++; + } else if( c2 ) { + *(vs->buffers + vs->curx + vs->curbuffer * ROWS * COLS + vs->cury * COLS ) = c2; + } + } + + if( vs->captions && vs->style == PAINT_ON ) { + if( vs->curx != COLS-1 ) { + vs->paintbuf[ vs->curx + vs->cury * COLS ] = c1; + vs->curx++; + } + + if( vs->curx != COLS-1 && c2 ) { + vs->paintbuf[ vs->curx + vs->cury * COLS ] = c2; + vs->curx++; + } else if( c2 ) { + vs->paintbuf[ vs->curx + vs->cury * COLS ] = c2; + } + } + + if( vs->captions && vs->style && vs->style <= ROLL_4 ) { + if( vs->curx != COLS-1 ) { + vs->hiddenbuf[ vs->curx ] = c1; + vs->curx++; + } else { + vs->hiddenbuf[ vs->curx ] = c1; + } + + if( vs->curx != COLS-1 && c2 ) { + vs->hiddenbuf[ vs->curx ] = c2; + vs->curx++; + } else if( c2 ) { + vs->hiddenbuf[ vs->curx ] = c2; + } + } +} + +void vbiscreen_reset( vbiscreen_t *vs ) +{ + if( !vs ) return; + clear_screen( vs ); + clear_hidden_pop( vs ); + clear_displayed_pop( vs ); + clear_hidden_roll( vs ); + vs->captions = 0; + vs->style = 0; +} + +void vbiscreen_composite_packed422_scanline( vbiscreen_t *vs, + unsigned char *output, + int width, int xpos, + int scanline ) +{ + int x=0, y=0, row=0, index=0; + + if( !vs ) return; + if( !output ) return; + if( scanline >= vs->y && scanline < vs->y + vs->height ) { + + if( 0 && !vs->captions ) + blit_colour_packed422_scanline( output + (vs->x*2), vs->width, + vs->bg_luma, vs->bg_cb, + vs->bg_cr ); + + index = vs->top_of_screen * COLS; + x = ( vs->x + vs->charwidth) & ~1; + for( row = 0; row < ROWS; row++ ) { + y = vs->y + row * vs->rowheight + vs->rowheight; + if( osd_string_visible( vs->line[ row ] ) ) { + if( scanline >= y && + scanline < y + vs->rowheight ) { + + int startx; + int strx; + + startx = x - xpos; + strx = 0; + + if( startx < 0 ) { + strx = -startx; + startx = 0; + } + + + if( startx < width ) { + + if( vs->captions ) + blit_colour_packed422_scanline( + output + (startx*2), + osd_string_get_width( vs->line[ row ] ), + vs->bg_luma, + vs->bg_cb, + vs->bg_cr ); + + osd_string_composite_packed422_scanline( + vs->line[ row ], + output + (startx*2), + output + (startx*2), + width - startx, + strx, + scanline - y ); + } + } + index++; + } + } + } +} + |