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
This commit is contained in:
David I. Lehn 2002-12-19 21:34:56 +00:00
parent 08d0c89de5
commit 61898506c8
8 changed files with 2321 additions and 1 deletions

View file

@ -233,7 +233,7 @@ GST_PLUGINS_ALL="\
mpegaudio mpegaudioparse mpegstream mpegtypes\
monoscope passthrough playondemand qtdemux rtjpeg silence sine\
smooth smpte spectrum speed stereo stereomono synaesthesia\
udp videocrop videoscale videotestsrc volenv volume\
udp vbidec videocrop videoscale videotestsrc volenv volume\
vumeter wavenc wavparse y4m"
dnl see if we can build C++ plug-ins
@ -1014,6 +1014,7 @@ gst/stereo/Makefile
gst/stereomono/Makefile
gst/synaesthesia/Makefile
gst/udp/Makefile
gst/vbidec/Makefile
gst/videoscale/Makefile
gst/videotestsrc/Makefile
gst/videocrop/Makefile

9
gst/vbidec/Makefile.am Normal file
View file

@ -0,0 +1,9 @@
plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@
plugin_LTLIBRARIES = libgstvbidec.la
libgstvbidec_la_SOURCES = gstvbidec.h gstvbidec.c \
vbidata.h vbidata.c \
vbiscreen.h vbiscreen.c
libgstvbidec_la_CFLAGS = $(GST_CFLAGS)
libgstvbidec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

372
gst/vbidec/gstvbidec.c Normal file
View file

@ -0,0 +1,372 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <string.h>
#include <inttypes.h>
#include <ctype.h>
#include <gst/gst.h>
#include "gstvbidec.h"
#include "vbidata.h"
#include "vbiscreen.h"
#define GST_TYPE_VBIDEC \
(gst_vbidec_get_type())
#define GST_VBIDEC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VBIDEC,GstVBIDec))
#define GST_VBIDEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VBIDEC,GstVBIDec))
#define GST_IS_VBIDEC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VBIDEC))
#define GST_IS_VBIDEC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VBIDEC))
//typedef struct _GstVBIDec GstVBIDec;
typedef struct _GstVBIDecClass GstVBIDecClass;
struct _GstVBIDec {
GstElement element;
/* pads */
GstPad *sinkpad,
*srcpad;
char caption[128];
vbiscreen_t *vbiscreen;
vbidata_t *vbidata;
int caption_type;
gboolean dvd_input;
};
struct _GstVBIDecClass {
GstElementClass parent_class;
};
GType gst_vbidec_get_type(void);
/* elementfactory information */
static GstElementDetails gst_vbidec_details = {
"VBI decoder",
"Codec/Video/Decoder",
"GPL",
"Decodes closed captions and XDS data from VBI data",
VERSION,
"David I. Lehn <dlehn@users.sourceforge.net>",
"(C) 2002"
};
/* VBIDec signals and args */
enum {
LAST_SIGNAL
};
enum {
ARG_0,
ARG_CAPTION_TYPE,
ARG_DVD_INPUT
};
GST_PAD_TEMPLATE_FACTORY (sink_template_factory,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"vbidec_sink",
"application/octet-stream",
NULL
)
);
GST_PAD_TEMPLATE_FACTORY (src_template_factory,
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"vbidec_src",
"text/plain",
NULL
)
);
#define GST_TYPE_VBIDEC_CAPTION_TYPE_TYPE (gst_vbidec_caption_type_get_type())
static GType
gst_vbidec_caption_type_get_type (void)
{
static GType vbidec_caption_type_type = 0;
static GEnumValue vbidec_caption_type[] = {
{ CAPTURE_OFF, "0", "Closed Captions off"},
{ CAPTURE_CC1, "1", "Closed Caption CC1"},
{ CAPTURE_CC2, "2", "Closed Caption CC2"},
{ CAPTURE_CC3, "4", "Closed Caption CC3"},
{ CAPTURE_CC4, "5", "Closed Caption CC4"},
{ CAPTURE_T1, "6", "Closed Caption T1"},
{ CAPTURE_T2, "7", "Closed Caption T2"},
{ CAPTURE_T3, "8", "Closed Caption T3"},
{ CAPTURE_T4, "9", "Closed Caption T4"},
{0, NULL, NULL},
};
if (!vbidec_caption_type_type) {
vbidec_caption_type_type = g_enum_register_static ("GstVBIDecCaptionTypeType", vbidec_caption_type);
}
return vbidec_caption_type_type;
}
static void gst_vbidec_class_init (GstVBIDecClass *klass);
static void gst_vbidec_init (GstVBIDec *vbidec);
static void gst_vbidec_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void gst_vbidec_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static void gst_vbidec_chain (GstPad *pad, GstBuffer *buffer);
static GstElementClass *parent_class = NULL;
/*static guint gst_vbidec_signals[LAST_SIGNAL] = { 0 };*/
GType
gst_vbidec_get_type (void)
{
static GType vbidec_type = 0;
if (!vbidec_type) {
static const GTypeInfo vbidec_info = {
sizeof(GstVBIDecClass),
NULL,
NULL,
(GClassInitFunc)gst_vbidec_class_init,
NULL,
NULL,
sizeof(GstVBIDec),
0,
(GInstanceInitFunc)gst_vbidec_init,
};
vbidec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstVBIDec", &vbidec_info, 0);
}
return vbidec_type;
}
static void
gst_vbidec_class_init(GstVBIDecClass *klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass*)klass;
gstelement_class = (GstElementClass*)klass;
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
gobject_class->set_property = gst_vbidec_set_property;
gobject_class->get_property = gst_vbidec_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CAPTION_TYPE,
g_param_spec_enum ("caption type", "caption type", "Closed Caption Type",
GST_TYPE_VBIDEC_CAPTION_TYPE_TYPE, CAPTURE_OFF, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DVD_INPUT,
g_param_spec_boolean ("dvd input", "dvd input", "VBI is encapsulated in MPEG2 GOP user_data field (as on DVDs)",
FALSE, G_PARAM_READWRITE));
}
static void
gst_vbidec_init (GstVBIDec *vbidec)
{
/* create the sink and src pads */
vbidec->sinkpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (sink_template_factory), "sink");
gst_element_add_pad (GST_ELEMENT (vbidec), vbidec->sinkpad);
gst_pad_set_chain_function (vbidec->sinkpad, GST_DEBUG_FUNCPTR (gst_vbidec_chain));
vbidec->srcpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (src_template_factory), "src");
gst_element_add_pad (GST_ELEMENT (vbidec), vbidec->srcpad);
vbidec->vbiscreen = vbiscreen_new(0, 0, 1.0, 0, (void *)vbidec);
vbidec->vbidata = vbidata_new_line(vbidec->vbiscreen, 0);
vbidec->caption_type = CAPTURE_OFF;
vbidata_capture_mode(vbidec->vbidata, vbidec->caption_type);
vbidec->dvd_input = FALSE;
}
static void
line21_decode(GstVBIDec *vbidec, guint8 *data, guint32 size)
{
vbidata_process_line(vbidec->vbidata, data, 0);
}
static void
dvd_user_data_decode(GstVBIDec *vbidec, guint8 *data, guint32 size)
{
//char caption[128];
//int ci; /* caption index */
int i; /* buf index */
int num_disp_field;
guint8 b1, b2;
int w;
//g_print("%%%% vbi decode\n");
//g_print("== %p %d\n", data, size);
i = 0;
/* Check for Closed Captioning data */
if (data[i] != 0x43 || data[i+1] != 0x43 ||
data[i+2] != 0x01 || data[i+3] != 0xf8) {
g_print ("non-CC data\n");
return;
}
//g_print ("CC data\n");
i += 4; /* above */
i += 4; /* ? */
num_disp_field = data[i] & 0x3f;
//g_print ("ndf %d\n", num_disp_field);
while ((data[i] & 0xfe) == 0xfe) {
if (data[i] & 0x1) {
b1 = data[i+1] & 0x7f;
b2 = data[i+2] & 0x7f;
w = (b2 << 8) | b1;
vbidata_process_16b(vbidec->vbidata, 0, w);
}
i += 3;
}
}
static void
gst_vbidec_chain (GstPad *pad, GstBuffer *buf)
{
GstVBIDec *vbidec = GST_VBIDEC (gst_pad_get_parent (pad));
guint32 size;
guint8 *data;
guint64 pts;
size = GST_BUFFER_SIZE (buf);
data = GST_BUFFER_DATA (buf);
pts = GST_BUFFER_TIMESTAMP (buf);
/*
g_print("** user_data: addr:%p len:%d state:%d\n", data, size, 0);
{
int i;
guint8 ud;
g_print("** \"");
for (i=0; i<size; i++) {
ud = data[i];
if (isprint((char)ud)) {
g_print("%c", (char)ud);
} else {
g_print("[0x%02x]", ud);
}
}
g_print("\"\n");
}
*/
if (vbidec->dvd_input) {
dvd_user_data_decode(vbidec, data, size);
} else {
line21_decode(vbidec, data, size);
}
gst_buffer_unref(buf);
}
void
gst_vbidec_show_text (GstVBIDec *vbidec, char *text, int len)
{
//fprintf(stderr, "%*s\n", len, text);
if (len > 0) {
if (GST_PAD_IS_USABLE (vbidec->srcpad)) {
GstBuffer *buf = gst_buffer_new_and_alloc (len);
memcpy (GST_BUFFER_DATA (buf), text, len);
GST_BUFFER_SIZE (buf) = len;
// FIXME
//GST_BUFFER_TIMESTAMP (buf) = vbidec->...
//...
//fprintf(stderr, "vbi text pushed\n");
gst_pad_push (vbidec->srcpad, buf);
}
}
}
static void
gst_vbidec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
GstVBIDec *vbidec;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_VBIDEC (object));
vbidec = GST_VBIDEC (object);
switch (prop_id) {
case ARG_DVD_INPUT:
vbidec->dvd_input = g_value_get_boolean(value);
break;
case ARG_CAPTION_TYPE:
vbidec->caption_type = g_value_get_enum(value);
vbidata_capture_mode(vbidec->vbidata, vbidec->caption_type);
break;
default:
break;
}
}
static void
gst_vbidec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
GstVBIDec *vbidec;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_VBIDEC (object));
vbidec = GST_VBIDEC (object);
switch (prop_id) {
case ARG_DVD_INPUT:
g_value_set_boolean(value, vbidec->dvd_input);
break;
case ARG_CAPTION_TYPE:
g_value_set_enum(value, vbidec->caption_type);
break;
default:
break;
}
}
static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
GstElementFactory *factory;
/* create an elementfactory for the vbidec element */
factory = gst_element_factory_new("vbidec",GST_TYPE_VBIDEC,
&gst_vbidec_details);
g_return_val_if_fail(factory != NULL, FALSE);
gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_PRIMARY);
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_template_factory));
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_template_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
return TRUE;
}
GstPluginDesc plugin_desc = {
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"vbidec",
plugin_init
};

22
gst/vbidec/gstvbidec.h Normal file
View file

@ -0,0 +1,22 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
typedef struct _GstVBIDec GstVBIDec;
void gst_vbidec_show_text (GstVBIDec *vbidec, char *text, int len);

1079
gst/vbidec/vbidata.c Normal file

File diff suppressed because it is too large Load diff

58
gst/vbidec/vbidata.h Normal file
View file

@ -0,0 +1,58 @@
/**
* Copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>.
* Copyright (c) 2002 Doug Bell <drbell@users.sourceforge.net>
*
* CC code from Nathan Laredo's ccdecode.
* Lots of 'hey what does this mean?' code from
* Billy Biggs and Doug Bell, like all the crap with
* XDS and stuff. Some help from Zapping's vbi library by
* Michael H. Schimek and others, released under the GPL.
*
* 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.
*/
#ifndef VBIDATA_H_INCLUDED
#define VBIDATA_H_INCLUDED
#include "vbiscreen.h"
/*#include "tvtimeosd.h"*/
typedef struct vbidata_s vbidata_t;
#define CAPTURE_OFF 0
#define CAPTURE_CC1 1
#define CAPTURE_CC2 2
#define CAPTURE_CC3 4
#define CAPTURE_CC4 5
#define CAPTURE_T1 6
#define CAPTURE_T2 7
#define CAPTURE_T3 8
#define CAPTURE_T4 9
vbidata_t *vbidata_new_file( const char *filename, vbiscreen_t *vs,
/*tvtime_osd_t* osd,*/ int verbose );
vbidata_t *vbidata_new_line( vbiscreen_t *vs, int verbose );
void vbidata_delete( vbidata_t *vbi );
void vbidata_reset( vbidata_t *vbi );
void vbidata_capture_mode( vbidata_t *vbi, int mode );
void vbidata_process_frame( vbidata_t *vbi, int printdebug );
void vbidata_process_line( vbidata_t *vbi, unsigned char *s, int bottom );
void vbidata_process_16b( vbidata_t *vbi, int bottom, int w );
#endif /* VBIDATA_H_INCLUDED */

730
gst/vbidec/vbiscreen.c Normal file
View file

@ -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++;
}
}
}
}

49
gst/vbidec/vbiscreen.h Normal file
View file

@ -0,0 +1,49 @@
/**
* 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.
*/
#ifndef HAVE_VBISCREEN_H
#define HAVE_VBISCREEN_H
typedef struct vbiscreen_s vbiscreen_t;
vbiscreen_t *vbiscreen_new( int video_width, int video_height,
double video_aspect, int verbose, void *user_data );
void vbiscreen_delete( vbiscreen_t *vs );
void vbiscreen_set_mode( vbiscreen_t *vs, int caption, int style);
void vbiscreen_new_caption( vbiscreen_t *vs, int indent, int ital,
unsigned int colour, int row );
void vbiscreen_tab( vbiscreen_t *vs, int cols );
void vbiscreen_delete_to_end( vbiscreen_t *vs );
void vbiscreen_backspace( vbiscreen_t *vs );
void vbiscreen_erase_displayed( vbiscreen_t *vs );
void vbiscreen_erase_non_displayed( vbiscreen_t *vs );
void vbiscreen_carriage_return( vbiscreen_t *vs );
void vbiscreen_end_of_caption( vbiscreen_t *vs );
void vbiscreen_print( vbiscreen_t *vs, char c1, char c2 );
void vbiscreen_composite_packed422_scanline( vbiscreen_t *vs,
unsigned char *output,
int width, int xpos,
int scanline );
void vbiscreen_dump_screen_text( vbiscreen_t *vs );
void vbiscreen_reset( vbiscreen_t *vs );
#endif