summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2001-11-28 22:19:10 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2001-11-28 22:19:10 +0000
commitd48b3bf8769a8ac1741d819289ed9ea117764bc5 (patch)
treeb90a868f2118128d8b0bcff135f9b0ac3d46ae73
parent157c020ba6d577c45678b7b59f96b3ca646fa525 (diff)
downloadxine-lib-d48b3bf8769a8ac1741d819289ed9ea117764bc5.tar.gz
xine-lib-d48b3bf8769a8ac1741d819289ed9ea117764bc5.tar.bz2
* OSD (On Screen Display) for rendering text and graphics into overlays
* reworked spu and overlay manager (multiple overlays supported) CVS patchset: 1126 CVS date: 2001/11/28 22:19:10
-rw-r--r--misc/Makefile.am3
-rw-r--r--misc/vga.xinefont.gzbin0 -> 2997 bytes
-rw-r--r--src/libspudec/spu.c5
-rw-r--r--src/libspudec/spu.h47
-rw-r--r--src/libspudec/xine_decoder.c664
-rw-r--r--src/video_out/video_out_xshm.c4
-rw-r--r--src/video_out/video_out_xv.c3
-rw-r--r--src/xine-engine/Makefile.am7
-rw-r--r--src/xine-engine/osd.c709
-rw-r--r--src/xine-engine/osd.h159
-rw-r--r--src/xine-engine/video_out.c39
-rw-r--r--src/xine-engine/video_out.h41
-rw-r--r--src/xine-engine/video_overlay.c550
-rw-r--r--src/xine-engine/video_overlay.h66
-rw-r--r--src/xine-engine/xine.c17
-rw-r--r--src/xine-engine/xine_internal.h4
16 files changed, 1658 insertions, 660 deletions
diff --git a/misc/Makefile.am b/misc/Makefile.am
index 018766043..606ba1fb3 100644
--- a/misc/Makefile.am
+++ b/misc/Makefile.am
@@ -5,7 +5,8 @@ EXTRA_DIST = autogen.sh upload.pl SlackBuild.in SlackBuild build_rpms.sh \
bin_SCRIPTS = xine-config
datadir = $(XINE_SKINDIR)
-data_DATA = xine_logo.png
+#this is just a hack. osd fonts should be installed in another dir
+data_DATA = xine_logo.png vga.xinefont.gz
debug:
diff --git a/misc/vga.xinefont.gz b/misc/vga.xinefont.gz
new file mode 100644
index 000000000..271de4445
--- /dev/null
+++ b/misc/vga.xinefont.gz
Binary files differ
diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c
index af342d146..b096417e5 100644
--- a/src/libspudec/spu.c
+++ b/src/libspudec/spu.c
@@ -35,7 +35,7 @@
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: spu.c,v 1.25 2001/11/26 20:02:33 guenter Exp $
+ * $Id: spu.c,v 1.26 2001/11/28 22:19:12 miguelfreitas Exp $
*
*/
@@ -49,9 +49,10 @@
#include <sys/stat.h>
#include <fcntl.h>
-#include "spu.h"
#include "video_out/alphablend.h"
#include "xineutils.h"
+#include "xine_internal.h"
+#include "spu.h"
/*
#define LOG_DEBUG 1
diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h
index e86adfde8..8571060e8 100644
--- a/src/libspudec/spu.h
+++ b/src/libspudec/spu.h
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: spu.h,v 1.6 2001/10/20 17:51:59 jcdutton Exp $
+ * $Id: spu.h,v 1.7 2001/11/28 22:19:12 miguelfreitas Exp $
*
* This file was originally part of the OMS program.
*
@@ -34,12 +34,10 @@
#include <inttypes.h>
#include "video_out.h"
+#include "video_overlay.h"
-#ifdef __GNUC__
-#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) {y: (_y), cr: (_cr), cb: (_cb)}
-#else
-#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) }
-#endif
+#define NUM_SEQ_BUFFERS 50
+#define MAX_STREAMS 32
typedef struct spu_clut_struct {
#ifdef WORDS_BIGENDIAN
@@ -95,4 +93,41 @@ void spu_draw_picture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl);
void spu_discover_clut (spu_state_t *state, vo_overlay_t *ovl);
void spu_update_menu (spu_state_t *state, vo_overlay_t *ovl);
+
+typedef struct spudec_stream_state_s {
+ spu_seq_t ra_seq;
+ uint32_t ra_complete;
+ uint32_t stream_filter;
+ spu_state_t state;
+ uint32_t vpts;
+ uint32_t pts;
+ int32_t overlay_handle;
+} spudec_stream_state_t;
+
+typedef struct spudec_decoder_s {
+ spu_decoder_t spu_decoder;
+
+ xine_t *xine;
+/* spu_seq_t seq_list[NUM_SEQ_BUFFERS]; */
+ spu_seq_t *cur_seq;
+ spudec_stream_state_t spu_stream_state[MAX_STREAMS];
+
+ video_overlay_event_t event;
+ video_overlay_object_t object;
+ int32_t menu_handle;
+
+ spu_seq_t *ra_seq;
+ int ra_complete;
+
+ uint32_t ovl_pts;
+ uint32_t buf_pts;
+ spu_state_t state;
+
+ vo_instance_t *vo_out;
+ vo_overlay_t overlay;
+ int ovl_caps;
+ int output_open;
+} spudec_decoder_t;
+
+
#endif
diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c
index 1f05e3ede..0c5811310 100644
--- a/src/libspudec/xine_decoder.c
+++ b/src/libspudec/xine_decoder.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_decoder.c,v 1.35 2001/11/18 03:53:24 guenter Exp $
+ * $Id: xine_decoder.c,v 1.36 2001/11/28 22:19:12 miguelfreitas Exp $
*
* stuff needed to turn libspu into a xine decoder plugin
*/
@@ -31,15 +31,13 @@
#include <sys/stat.h>
#include <fcntl.h>
-#include "spu.h"
#include "buffer.h"
#include "events.h"
#include "xine_internal.h"
#include "video_out/alphablend.h"
#include "xine-engine/bswap.h"
#include "xineutils.h"
-
-static void spudec_print_overlay( vo_overlay_t *ovl );
+#include "spu.h"
/*
#define LOG_DEBUG 1
@@ -83,90 +81,6 @@ static clut_t __default_clut[] = {
CLUT_Y_CR_CB_INIT(0x28, 0x6d, 0xef)
};
-#define NUM_SEQ_BUFFERS 50
-#define MAX_OBJECTS 50
-#define MAX_STREAMS 32
-#define MAX_EVENTS 50
-#define MAX_SHOWING 5
-
-#define EVENT_NULL 0
-#define EVENT_SHOW_SPU 1
-#define EVENT_HIDE_SPU 2
-#define EVENT_HIDE_MENU 3
-#define EVENT_MENU_SPU 4
-#define EVENT_MENU_BUTTON 5
-#define EVENT_DELETE_RESOURCE 6 /* Maybe release handle will do this */
-#define EVENT_SHOW_OSD 7 /* Not yet implemented */
-
-typedef struct spu_object_s {
- int32_t handle; /* Used to match Show and Hide events. */
- uint32_t object_type; /* 0=Subtitle, 1=Menu */
- uint32_t pts; /* Needed for Menu button compares */
- vo_overlay_t *overlay; /* The image data. */
- uint32_t palette_type; /* 1 Y'CrCB, 2 R'G'B' */
- uint32_t *palette; /* If NULL, no palette contained in this event. */
-} spu_object_t;
-
-/* This will hold all details of an event item, needed for event queue to function */
-typedef struct spu_overlay_event_s {
- uint32_t event_type; /* Show SPU, Show OSD, Hide etc. */
- uint32_t vpts; /* Time when event will action. 0 means action now */
-/* Once video_out blend_yuv etc. can take rle_elem_t with Colour, blend and length information.
- * we can remove clut and blend from this structure.
- * This will allow for many more colours for OSD.
- */
- spu_object_t object; /* The image data. */
-} spu_overlay_event_t;
-
-typedef struct spu_overlay_events_s {
- spu_overlay_event_t *event;
- uint32_t next_event;
-} spu_overlay_events_t;
-
-typedef struct spu_showing_s {
- int32_t handle; /* -1 means not allocated */
-} spu_showing_t;
-
-
-typedef struct spudec_stream_state_s {
- spu_seq_t ra_seq;
- uint32_t ra_complete;
- uint32_t stream_filter;
- spu_state_t state;
- uint32_t vpts;
- uint32_t pts;
-} spudec_stream_state_t;
-
-typedef struct spudec_decoder_s {
- spu_decoder_t spu_decoder;
- ovl_src_t ovl_src;
-
- xine_t *xine;
-/* spu_seq_t seq_list[NUM_SEQ_BUFFERS]; */
- spu_seq_t *cur_seq;
- spudec_stream_state_t spu_stream_state[MAX_STREAMS];
- pthread_mutex_t spu_events_mutex;
- spu_overlay_events_t spu_events[MAX_EVENTS];
- spu_overlay_event_t event;
- spu_object_t object;
- pthread_mutex_t spu_objects_mutex;
- spu_object_t spu_objects[MAX_OBJECTS];
- pthread_mutex_t spu_showing_mutex; /* Probably not needed */
- spu_showing_t spu_showing[MAX_SHOWING];
- spu_seq_t *ra_seq;
- int ra_complete;
-
- uint32_t ovl_pts;
- uint32_t buf_pts;
- spu_state_t state;
-
- vo_instance_t *vo_out;
- vo_overlay_t overlay;
- int ovl_caps;
- int output_open;
-
-} spudec_decoder_t;
-
static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
int type = buf_type & 0xFFFF0000;
return (type == BUF_SPU_PACKAGE || type == BUF_SPU_CLUT || type == BUF_SPU_SUBP_CONTROL) ;
@@ -175,6 +89,7 @@ static int spudec_can_handle (spu_decoder_t *this_gen, int buf_type) {
/* FIXME: This function needs checking */
static void spudec_reset (spudec_decoder_t *this) {
int i;
+
this->ovl_pts = 0;
this->buf_pts = 0;
@@ -187,50 +102,9 @@ static void spudec_reset (spudec_decoder_t *this) {
for (i=0; i < MAX_STREAMS; i++) {
this->spu_stream_state[i].stream_filter = 1; /* So it works with non-navdvd plugins */
this->spu_stream_state[i].ra_complete = 1;
+ this->spu_stream_state[i].overlay_handle = -1;
}
- for (i=0; i < MAX_EVENTS; i++) {
- if (this->spu_events[i].event == NULL) {
-#ifdef LOG_DEBUG
- printf ("spu: MALLOC1: this->spu_events[%d].event %p, len=%d\n",
- i,
- this->spu_events[i].event,
- sizeof(spu_overlay_event_t));
-#endif
- this->spu_events[i].event = xine_xmalloc (sizeof(spu_overlay_event_t));
-#ifdef LOG_DEBUG
- printf ("spu: MALLOC2: this->spu_events[%d].event %p, len=%d\n",
- i,
- this->spu_events[i].event,
- sizeof(spu_overlay_event_t));
-#endif
- this->spu_events[i].event->event_type = 0; /* Empty slot */
- }
- }
- for (i=0; i < MAX_OBJECTS; i++) {
- this->spu_objects[i].handle = -1;
- }
- /* Initialise the menu object */
- this->spu_objects[1].handle=1;
- this->spu_objects[1].object_type=1;
- this->spu_objects[1].pts=0;
-#ifdef LOG_DEBUG
- printf ("spu: MALLOC1: this->spu_objects[1].overlay %p, len=%d\n",
- this->spu_objects[1].overlay, sizeof(vo_overlay_t));
-#endif
- this->spu_objects[1].overlay = xine_xmalloc (sizeof(vo_overlay_t));
-#ifdef LOG_DEBUG
- printf ("spu: MALLOC2: this->spu_objects[1].overlay %p, len=%d\n",
- this->spu_objects[1].overlay, sizeof(vo_overlay_t));
-#endif
-/* xine_xmalloc does memset */
-/* memset(this->spu_objects[1].overlay,0,sizeof(vo_overlay_t));
- */
-
- pthread_mutex_init (&this->spu_events_mutex,NULL);
- pthread_mutex_init (&this->spu_objects_mutex,NULL);
- pthread_mutex_init (&this->spu_showing_mutex,NULL);
-
/* I don't think I need this.
this->cur_seq = this->ra_seq = this->seq_list;
*/
@@ -249,131 +123,13 @@ static void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) {
/* FIXME:Do we really need a default clut? */
memcpy(this->state.clut, __default_clut, sizeof(this->state.clut));
this->state.need_clut = 1;
- vo_out->register_ovl_src(vo_out, &this->ovl_src);
-}
-
-/* allocate a handle from the object pool
- */
-static int32_t spu_get_handle(spudec_decoder_t *this) {
- int n;
- n=0;
- do {
- n++;
- } while ( ( n<MAX_OBJECTS ) && ( this->spu_objects[n].handle > -1 ) );
- if (n >= MAX_OBJECTS) return -1;
- this->spu_objects[n].handle=n;
- return n;
-}
-
-/* allocate a menu handle from the object pool
- */
-static int32_t spu_get_menu_handle(spudec_decoder_t *this) {
- return 1; /* This might be dynamic later */
-}
-
-/* free a handle from the object pool
- */
-static void spu_free_handle(spudec_decoder_t *this, int32_t handle) {
- this->spu_objects[handle].handle = -1;
-}
-
-/* add an event to the events queue, sort the queue based on vpts.
- * This can be the API entry point for DVD subtitles.
- * In future this could also be the entry point for OSD as well as other Subtitle formats.
- * One calls this function with an event, the event contains an overlay and a vpts when to action/process it.
- * vpts of 0 means action the event now.
- * One also has a handle, so one can match show and hide events.
- * FIXME: Implement Event queue locking. A different thread calls spu_get_overlay, which removes events from the queue.
- */
-static int32_t spu_add_event(spudec_decoder_t *this, spu_overlay_event_t *event) {
- int found;
- uint32_t last_event,this_event,new_event;
- new_event=0;
- /* We skip the 0 entry because that is used as a pointer to the first event.*/
- /* Find a free event slot */
-#ifdef LOG_DEBUG
- printf ("spu: 284MUTEX1:spu_events lock");
-#endif
- pthread_mutex_lock (&this->spu_events_mutex);
-#ifdef LOG_DEBUG
- printf ("spu:->ok\n");
-#endif
- do {
- new_event++;
- } while ((new_event<MAX_EVENTS) && (this->spu_events[new_event].event->event_type > 0));
- if (new_event >= MAX_EVENTS) {
- pthread_mutex_unlock (&this->spu_events_mutex);
- return -1;
- }
- /* Find position in event queue to be added. */
- this_event=0;
- found=0;
- /* Find where in the current queue to insert the event. I.E. Sort it. */
- do {
- last_event=this_event;
- this_event=this->spu_events[last_event].next_event;
- if (this_event == 0) {
- found=1;
- break;
- }
-#ifdef LOG_DEBUG
- printf ("spu:this_event=%d vpts %d\n",this_event, this->spu_events[this_event].event->vpts);
-#endif
- if (this->spu_events[this_event].event->vpts > event->vpts ) {
- found=2;
- break;
- }
- } while ((this_event != 0) && (found == 0));
- if (last_event >= MAX_EVENTS) {
- pthread_mutex_unlock (&this->spu_events_mutex);
- fprintf(stderr, "No spare subtitle event slots\n");
- return -1;
- }
- /* memcpy everything except the actual image */
- this->spu_events[last_event].next_event=new_event;
- this->spu_events[new_event].next_event=this_event;
- if ( this->spu_events[new_event].event == NULL ) {
- fprintf(stderr,"COMPLAIN BIG TIME!\n");
- }
- this->spu_events[new_event].event->event_type=event->event_type;
- this->spu_events[new_event].event->vpts=event->vpts;
- this->spu_events[new_event].event->object.handle=event->object.handle;
-#ifdef LOG_DEBUG
- printf ("spu: 323MALLOC1: this->spu_events[new_event=%d].event->object.overlay %p, len=%d\n",
- new_event,
- this->spu_events[new_event].event->object.overlay,
- sizeof(vo_overlay_t));
-#endif
- this->spu_events[new_event].event->object.overlay = xine_xmalloc (sizeof(vo_overlay_t));
-#ifdef LOG_DEBUG
- printf ("spu: 328MALLOC2: this->spu_events[new_event=%d].event->object.overlay %p, len=%d\n",
- new_event,
- this->spu_events[new_event].event->object.overlay,
- sizeof(vo_overlay_t));
-#endif
- memcpy(this->spu_events[new_event].event->object.overlay,
- event->object.overlay, sizeof(vo_overlay_t));
- memset(event->object.overlay,0,sizeof(vo_overlay_t));
-// spudec_print_overlay( event->object.overlay );
-// spudec_print_overlay( this->spu_events[new_event].event->object.overlay );
- pthread_mutex_unlock (&this->spu_events_mutex);
-
- return new_event;
}
-/* empty the object queue
- * release all handles currently allocated.
- * IMPLEMENT ME.
- */
-static void spu_free_all_handles(spudec_decoder_t *this) {
-return;
-}
static void spu_process (spudec_decoder_t *this, uint32_t stream_id) {
// spu_overlay_event_t *event;
// spu_object_t *object;
// vo_overlay_t *overlay;
- int handle;
int pending = 1;
this->cur_seq = &this->spu_stream_state[stream_id].ra_seq;
@@ -392,12 +148,7 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) {
this->state.menu = 0; /* 0 - No value, 1 - Forced Display. */
this->state.delay = 0;
this->cur_seq->finished=0;
- handle=spu_get_handle(this);
- if (handle < 0) {
- printf("No SPU Handles left\n");
- return;
- }
-
+
do {
if (!this->spu_stream_state[stream_id].ra_seq.finished) {
@@ -414,7 +165,6 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) {
#ifdef LOG_DEBUG
printf ("spu: Dropping SPU channel %d\n", stream_id);
#endif
- spu_free_handle(this, handle);
return;
}
if ((this->state.modified) ) {
@@ -426,45 +176,56 @@ static void spu_process (spudec_decoder_t *this, uint32_t stream_id) {
if (this->state.menu == 0) {
/* Subtitle */
- this->event.object.handle = handle;
- /* FIXME: memcpy maybe. */
-#ifdef LOG_DEBUG
- printf ("spu: 403MALLOC: this->event.object.overlay=%p\n",
- this->event.object.overlay);
-#endif
- this->event.object.overlay = malloc(sizeof(vo_overlay_t));
+ if( this->spu_stream_state[stream_id].overlay_handle < 0 ) {
+ this->spu_stream_state[stream_id].overlay_handle =
+ this->vo_out->overlay_source->get_handle(this->vo_out->overlay_source, 0);
+ }
+
+ if( this->spu_stream_state[stream_id].overlay_handle < 0 ) {
+ printf("libspudec: No video_overlay handles left for SPU\n");
+ return;
+ }
+
+ this->event.object.handle = this->spu_stream_state[stream_id].overlay_handle;
+
memcpy(this->event.object.overlay,
&this->overlay,
sizeof(vo_overlay_t));
this->overlay.rle=NULL;
-#ifdef LOG_DEBUG
- printf ("spu: 409MALLOC: this->event.object.overlay=%p\n",
- this->event.object.overlay);
-#endif
+
this->event.event_type = this->state.visible;
+
+ /* event hide event must free the handle after use */
+ if( this->event.event_type == EVENT_HIDE_SPU ) {
+ this->spu_stream_state[stream_id].overlay_handle = -1;
+ }
+
this->event.vpts = this->spu_stream_state[stream_id].vpts+(this->state.delay*1000);
+
+ /*
+ printf("spu event %d handle: %d vpts: %d\n", this->event.event_type,
+ this->event.object.handle, this->event.vpts );
+ */
} else {
/* Menu */
- spu_free_handle(this, handle);
- this->event.object.handle = spu_get_menu_handle(this);
- /* FIXME: memcpy maybe. */
-#ifdef LOG_DEBUG
- printf ("spu:418MALLOC: this->event.object.overlay=%p\n",
- this->event.object.overlay);
-#endif
- this->event.object.overlay = malloc(sizeof(vo_overlay_t));
+ if( this->menu_handle < 0 )
+ this->menu_handle = this->vo_out->overlay_source->get_handle(this->vo_out->overlay_source,1);
+
+ if( this->menu_handle < 0 ) {
+ printf("libspudec: No video_overlay handles left for menu\n");
+ return;
+ }
+ this->event.object.handle = this->menu_handle;
+
memcpy(this->event.object.overlay,
&this->overlay,
sizeof(vo_overlay_t));
this->overlay.rle=NULL;
-#ifdef LOG_DEBUG
- printf ("spu: 424MALLOC: this->event.object.overlay=%p\n",
- this->event.object.overlay);
-#endif
+
this->event.event_type = EVENT_MENU_SPU;
this->event.vpts = this->spu_stream_state[stream_id].vpts+(this->state.delay*1000);
}
- spu_add_event(this, &this->event);
+ this->vo_out->overlay_source->add_event(this->vo_out->overlay_source, (void *)&this->event);
} else {
pending = 0;
}
@@ -509,7 +270,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
return;
if (buf->PTS) {
- metronom_t *metronom = this->ovl_src.metronom;
+ metronom_t *metronom = this->xine->metronom;
uint32_t vpts = metronom->got_spu_packet(metronom, buf->PTS, 0, buf->SCR);
if (vpts < this->buf_pts) {
/* FIXME: Don't do this yet,
@@ -546,9 +307,22 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) {
static void spudec_close (spu_decoder_t *this_gen) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
+ int i;
- this->vo_out->unregister_ovl_src(this->vo_out, &this->ovl_src);
+ if( this->menu_handle >= 0 )
+ this->vo_out->overlay_source->free_handle(this->vo_out->overlay_source,
+ this->menu_handle);
+ this->menu_handle = -1;
+
+
+ for (i=0; i < MAX_STREAMS; i++) {
+ if( this->spu_stream_state[i].overlay_handle >= 0 )
+ this->vo_out->overlay_source->free_handle(this->vo_out->overlay_source,
+ this->spu_stream_state[i].overlay_handle);
+ this->spu_stream_state[i].overlay_handle = -1;
+ }
}
+
/* This function is probably not needed now */
static void spudec_nextseq(spudec_decoder_t* this) {
spu_seq_t *tmp_seq = this->cur_seq + 1;
@@ -582,303 +356,6 @@ static void spudec_print_overlay( vo_overlay_t *ovl ) {
return;
}
-/* FIXME:Some optimization needs to happen here. */
-static void spu_process_event( spudec_decoder_t *this, int vpts ) {
- int32_t handle;
- uint32_t this_event;
-// uint32_t vpts;
-// uint32_t pts;
-// int i;
-// vo_overlay_t overlay;
-#ifdef LOG_DEBUG
- printf ("spu: 557MUTEX1:spu_events lock");
-#endif
- pthread_mutex_lock (&this->spu_events_mutex);
-#ifdef LOG_DEBUG
- printf ("spu: -> ok.\n");
-#endif
- this_event=this->spu_events[0].next_event;
- if ((!this_event) || (vpts < this->spu_events[this_event].event->vpts) ) {
- pthread_mutex_unlock (&this->spu_events_mutex);
- return;
- }
-
- handle=this->spu_events[this_event].event->object.handle;
- switch( this->spu_events[this_event].event->event_type ) {
- case EVENT_SHOW_SPU:
-#ifdef LOG_DEBUG
- printf ("spu: SHOW SPU NOW\n");
-#endif
- if (this->spu_events[this_event].event->object.overlay != NULL) {
- this->spu_objects[handle].handle = handle;
-#ifdef LOG_DEBUG
- printf ("spu: POINTER1: this->spu_objects[handle=%d].overlay=%p\n",
- handle,
- this->spu_objects[handle].overlay);
-#endif
- this->spu_objects[handle].overlay = this->spu_events[this_event].event->object.overlay;
-#ifdef LOG_DEBUG
- printf ("spu: POINTER2: this->spu_objects[handle=%d].overlay=%p\n",
- handle,
- this->spu_objects[handle].overlay);
-#endif
- this->spu_events[this_event].event->object.overlay = NULL;
- }
- this->spu_showing[1].handle = handle;
- break;
-
- case EVENT_HIDE_SPU:
-#ifdef LOG_DEBUG
- printf ("spu: HIDE SPU NOW\n");
-#endif
- this->spu_showing[1].handle = -1;
- if(this->spu_objects[handle].overlay->rle) {
-#ifdef LOG_DEBUG
- printf ("spu: FREE1: this->spu_objects[%d].overlay->rle %p\n",
- handle,
- this->spu_objects[handle].overlay->rle);
-#endif
- free(this->spu_objects[handle].overlay->rle);
- this->spu_objects[handle].overlay->rle = NULL;
-#ifdef LOG_DEBUG
- printf ("spu: FREE2: this->spu_objects[%d].overlay->rle %p\n",
- handle,
- this->spu_objects[handle].overlay->rle);
-#endif
- }
-#ifdef LOG_DEBUG
- printf ("spu: RLE clear=%08X\n",(uint32_t)this->spu_objects[handle].overlay->rle);
-#endif
- if (this->spu_objects[handle].overlay) {
-#ifdef LOG_DEBUG
- printf ("spu: FREE1: this->spu_objects[%d].overlay %p\n",
- handle,
- this->spu_objects[handle].overlay);
-#endif
- free(this->spu_objects[handle].overlay);
- this->spu_objects[handle].overlay = NULL;
-#ifdef LOG_DEBUG
- printf ("spu: FREE2: this->spu_objects[%d].overlay %p\n",
- handle,
- this->spu_objects[handle].overlay);
-#endif
- }
- spu_free_handle( this, handle );
- break;
-
- case EVENT_HIDE_MENU:
-#ifdef LOG_DEBUG
- printf ("spu: HIDE MENU NOW %d\n",handle);
-#endif
- this->spu_showing[1].handle = -1;
- if(this->spu_objects[handle].overlay->rle) {
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE1: this->spu_objects[%d].overlay->rle %p\n",
- handle,
- this->spu_objects[handle].overlay->rle);
-#endif
- free(this->spu_objects[handle].overlay->rle);
- this->spu_objects[handle].overlay->rle = NULL;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE2: this->spu_objects[%d].overlay->rle %p\n",
- handle,
- this->spu_objects[handle].overlay->rle);
-#endif
- }
-
- /* FIXME: maybe free something here */
- /* spu_free_handle( this, handle ); */
- break;
-
- case EVENT_MENU_SPU:
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "MENU SPU NOW\n");
-#endif
- if (this->spu_events[this_event].event->object.overlay != NULL) {
- vo_overlay_t *overlay = this->spu_objects[handle].overlay;
- vo_overlay_t *event_overlay = this->spu_events[this_event].event->object.overlay;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "event_overlay\n");
-#endif
- spudec_print_overlay(event_overlay);
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "overlay\n");
-#endif
- spudec_print_overlay(overlay);
-
- this->spu_objects[handle].handle = handle; /* This should not change for menus */
- /* If rle is not empty, free it first */
- if(overlay && overlay->rle) {
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE1: overlay->rle %p\n",
- overlay->rle);
-#endif
- free (overlay->rle);
- overlay->rle = NULL;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE2: overlay->rle %p\n",
- overlay->rle);
-#endif
- }
- overlay->rle = event_overlay->rle;
- overlay->data_size = event_overlay->data_size;
- overlay->num_rle = event_overlay->num_rle;
- overlay->x = event_overlay->x;
- overlay->y = event_overlay->y;
- overlay->width = event_overlay->width;
- overlay->height = event_overlay->height;
- overlay->rgb_clut = event_overlay->rgb_clut;
- if((event_overlay->color[0] +
- event_overlay->color[1] +
- event_overlay->color[2] +
- event_overlay->color[3]) > 0 ) {
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "mixing clut\n");
-#endif
- overlay->color[0] = event_overlay->color[0];
- overlay->color[1] = event_overlay->color[1];
- overlay->color[2] = event_overlay->color[2];
- overlay->color[3] = event_overlay->color[3];
- }
- if((event_overlay->trans[0] +
- event_overlay->trans[1] +
- event_overlay->trans[2] +
- event_overlay->trans[3]) > 0 ) {
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "mixing trans\n");
-#endif
- overlay->trans[0] = event_overlay->trans[0];
- overlay->trans[1] = event_overlay->trans[1];
- overlay->trans[2] = event_overlay->trans[2];
- overlay->trans[3] = event_overlay->trans[3];
- }
- this->spu_showing[1].handle = handle;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "overlay after\n");
-#endif
- spudec_print_overlay(overlay);
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE1: event_overlay %p\n",
- this->spu_events[this_event].event->object.overlay = NULL);
-#endif
- /* The null test was done at the start of this case statement */
- free (this->spu_events[this_event].event->object.overlay);
- this->spu_events[this_event].event->object.overlay = NULL;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE2: event_ovlerlay %p\n",
- this->spu_events[this_event].event->object.overlay);
-#endif
- }
- break;
-
- case EVENT_MENU_BUTTON:
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "MENU BUTTON NOW\n");
-#endif
- if (this->spu_events[this_event].event->object.overlay != NULL) {
- vo_overlay_t *overlay = this->spu_objects[handle].overlay;
- vo_overlay_t *event_overlay = this->spu_events[this_event].event->object.overlay;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "event_overlay\n");
-#endif
- spudec_print_overlay(event_overlay);
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "overlay\n");
-#endif
- spudec_print_overlay(overlay);
- this->spu_objects[handle].handle = handle; /* This should not change for menus */
- overlay->clip_top = event_overlay->clip_top;
- overlay->clip_bottom = event_overlay->clip_bottom;
- overlay->clip_left = event_overlay->clip_left;
- overlay->clip_right = event_overlay->clip_right;
- //overlay->rgb_clut = event_overlay->rgb_clut; /* May needed later for OSD */
- if((event_overlay->color[0] +
- event_overlay->color[1] +
- event_overlay->color[2] +
- event_overlay->color[3]) > 0 ) {
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "mixing clut\n");
-#endif
- overlay->color[0] = event_overlay->color[0];
- overlay->color[1] = event_overlay->color[1];
- overlay->color[2] = event_overlay->color[2];
- overlay->color[3] = event_overlay->color[3];
- }
- if((event_overlay->trans[0] +
- event_overlay->trans[1] +
- event_overlay->trans[2] +
- event_overlay->trans[3]) > 0 ) {
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "mixing trans\n");
-#endif
- overlay->trans[0] = event_overlay->trans[0];
- overlay->trans[1] = event_overlay->trans[1];
- overlay->trans[2] = event_overlay->trans[2];
- overlay->trans[3] = event_overlay->trans[3];
- }
- this->spu_showing[1].handle = handle;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "overlay after\n");
-#endif
- spudec_print_overlay(overlay);
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE1: event_overlay %p\n",
- this->spu_events[this_event].event->object.overlay = NULL);
-#endif
- /* The null test was done at the start of this case statement */
- free (this->spu_events[this_event].event->object.overlay);
- this->spu_events[this_event].event->object.overlay = NULL;
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "FREE2: event_ovlerlay %p\n",
- this->spu_events[this_event].event->object.overlay);
-#endif
- }
- break;
-
- default:
-#ifdef LOG_DEBUG
- xprintf (VERBOSE|SPU, "Unhandled event type\n");
-#endif
- break;
-
- }
- this->spu_events[0].next_event = this->spu_events[this_event].next_event;
- this->spu_events[this_event].next_event = 0;
- this->spu_events[this_event].event->event_type = 0;
- pthread_mutex_unlock (&this->spu_events_mutex);
-}
-
-/* This is called from video_out and should return one image.
- * Repeated calls will display the next image.
- * until the last image is reached, when a NULL is returned
- * and the pointer starts from the beginning again.
- * For now, a max of 5 diffent images can be displayed at once.
- * Maybe we should add a callback instead of calling the function all the time.
- * We could rename this then to "Render overlay"
- * This function needs an API change, to add a callback function to do the actual overlay.
- * In this way we can get multiple objects displayed at the same time.
- * i.e. Subtitles and OSD.
- * Currently, only one object can be displayed at the same time.
- * The first checkin of this code should add no more functionality than the current code.
- * It was just be checked in so others can test it.
- */
-
-static vo_overlay_t* spudec_get_overlay(ovl_src_t *ovl_src, int vpts) {
- int32_t handle;
- spudec_decoder_t *this = (spudec_decoder_t*) ovl_src->src_gen;
-
- /* Look at next event, if current video vpts > first event on queue, process the event
- * else just continue
- */
- spu_process_event( this, vpts );
- /* Scan through 5 entries and display any present.
- * Currently, only 1 entry is scanned, until API can change.
- */
- handle=this->spu_showing[1].handle; /* handle is only valid if the object is currently visable. */
- if (handle < 0) return NULL;
- return this->spu_objects[handle].overlay;
-}
-
static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
spudec_decoder_t *this = (spudec_decoder_t *) this_gen;
xine_spu_event_t *event = (xine_spu_event_t *) event_gen;
@@ -890,7 +367,7 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
switch (event->event.type) {
case XINE_EVENT_SPU_BUTTON:
{
- spu_overlay_event_t *overlay_event = NULL;
+ video_overlay_event_t *overlay_event = NULL;
vo_overlay_t *overlay = NULL;
spu_button_t *but = event->data;
#ifdef LOG_DEBUG
@@ -898,7 +375,7 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
overlay_event,
sizeof(spu_overlay_event_t));
#endif
- overlay_event = xine_xmalloc (sizeof(spu_overlay_event_t));
+ overlay_event = xine_xmalloc (sizeof(video_overlay_event_t));
#ifdef LOG_DEBUG
xprintf (VERBOSE|SPU, "MALLOC2: overlay_event %p, len=%d\n",
overlay_event,
@@ -928,7 +405,7 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
if (!this->state.menu) return;
if (but->show) {
- overlay_event->object.handle = spu_get_menu_handle(this);
+ overlay_event->object.handle = this->menu_handle;
overlay_event->object.overlay=overlay;
overlay_event->event_type = EVENT_MENU_BUTTON;
overlay_event->vpts = 0; /* Activate it NOW */
@@ -944,13 +421,12 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
overlay->trans[1] = but->trans[1];
overlay->trans[2] = but->trans[2];
overlay->trans[3] = but->trans[3];
- spu_add_event(this, overlay_event);
} else {
- overlay_event->object.handle = spu_get_menu_handle(this);
+ overlay_event->object.handle = this->menu_handle;
overlay_event->event_type = EVENT_HIDE_MENU;
overlay_event->vpts = 0; /* Activate it NOW */
- spu_add_event(this, overlay_event);
}
+ this->vo_out->overlay_source->add_event(this->vo_out->overlay_source, (void *)overlay_event);
}
break;
case XINE_EVENT_SPU_CLUT:
@@ -963,21 +439,6 @@ static void spudec_event_listener(void *this_gen, xine_event_t *event_gen) {
}
}
break;
- /* What is this for?
- * This event is for GUI -> NAVDVD plugin
- * SPUDEC will have to use a different EVENT
- * if it needs this for CLUT auto detect.
- * ->that was a patch to redetect clut on spu channel change.
- * not very important, i will take a look when i have time. [MF]
- */
- /* FIXME
- case XINE_UI_GET_SPU_LANG:
- {
- this->state.need_clut = 1;
- }
- break;
- */
-
}
}
@@ -1008,9 +469,10 @@ spu_decoder_t *init_spu_decoder_plugin (int iface_version, xine_t *xine) {
this->spu_decoder.get_identifier = spudec_get_id;
this->spu_decoder.priority = 1;
- this->ovl_src.src_gen = this;
- this->ovl_src.get_overlay = spudec_get_overlay;
this->xine = xine;
+
+ this->menu_handle = -1;
+ this->event.object.overlay = malloc(sizeof(vo_overlay_t));
xine_register_event_listener(xine, spudec_event_listener, this);
diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c
index 4a919fd7f..d6a744f80 100644
--- a/src/video_out/video_out_xshm.c
+++ b/src/video_out/video_out_xshm.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out_xshm.c,v 1.51 2001/11/18 03:53:24 guenter Exp $
+ * $Id: video_out_xshm.c,v 1.52 2001/11/28 22:19:12 miguelfreitas Exp $
*
* video_out_xshm.c, X11 shared memory extension interface for xine
*
@@ -720,7 +720,7 @@ static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overla
int i;
clut_t* clut = (clut_t*) overlay->color;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
*((uint32_t *)&clut[i]) =
this->yuv2rgb->yuv2rgb_single_pixel_fun(this->yuv2rgb,
clut[i].y, clut[i].cb, clut[i].cr);
diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c
index be6bf45a0..938d6349f 100644
--- a/src/video_out/video_out_xv.c
+++ b/src/video_out/video_out_xv.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out_xv.c,v 1.80 2001/11/23 22:29:45 f1rmb Exp $
+ * $Id: video_out_xv.c,v 1.81 2001/11/28 22:19:12 miguelfreitas Exp $
*
* video_out_xv.c, X11 video extension interface for xine
*
@@ -1364,7 +1364,6 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
} else if(!strcmp(attr[k].name, "XV_FILTER")) {
int xv_filter;
/* This setting is specific to Permedia 2/3 cards. */
- printf("XV_FILTER (%d->%d)/n",attr[k].min_value, attr[k].max_value);
xv_filter = config->register_range (config, "video.XV_FILTER", 0,
attr[k].min_value, attr[k].max_value,
"bilinear scaling mode (permedia 2/3)",
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am
index ad67530f2..ccf76e5e7 100644
--- a/src/xine-engine/Makefile.am
+++ b/src/xine-engine/Makefile.am
@@ -9,8 +9,9 @@ lib_LTLIBRARIES = libxine.la
libxine_la_SOURCES = xine.c metronom.c configfile.c buffer.c \
load_plugins.c video_decoder.c buffer_types.c \
- audio_decoder.c video_out.c audio_out.c resample.c events.c lrb.c
-libxine_la_LIBADD = $(THREAD_LIBS) $(DYNAMIC_LD_LIBS) -lm
+ audio_decoder.c video_out.c audio_out.c resample.c events.c lrb.c \
+ video_overlay.c osd.c
+libxine_la_LIBADD = $(THREAD_LIBS) $(DYNAMIC_LD_LIBS) -lm -lz
libxine_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
@@ -18,7 +19,7 @@ libxine_la_LDFLAGS = \
include_HEADERS = buffer.h metronom.h configfile.h \
audio_out.h resample.h video_out.h xine_internal.h spu_decoder.h \
- events.h lrb.h
+ events.h lrb.h video_overlay.h osd.h
noinst_HEADERS = bswap.h
diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c
new file mode 100644
index 000000000..aaad50a63
--- /dev/null
+++ b/src/xine-engine/osd.c
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine 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.
+ *
+ * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * OSD stuff (text and graphic primitives)
+ */
+
+#define __OSD_C__
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <zlib.h>
+
+#include "events.h"
+#include "video_overlay.h"
+#include "xine_internal.h"
+#include "video_out/alphablend.h"
+#include "xine-engine/bswap.h"
+#include "xineutils.h"
+#include "video_out.h"
+#include "osd.h"
+
+/*
+#define LOG_DEBUG 1
+*/
+
+#ifdef DEBUG
+
+# ifdef __GNUC__
+# define LOG(lvl, fmt...) fprintf (stderr, fmt);
+# else
+# define LOG(lvl, ...) fprintf (stderr, __VA_ARGS__);
+# endif
+
+#else /* !DEBUG */
+
+# ifdef __GNUC__
+# define LOG(lvl, fmt...)
+# else
+# define LOG(lvl, ...)
+# endif
+
+#endif /* !DEBUG */
+
+
+#define MAX(a,b) ( (a) > (b) ) ? (a) : (b)
+#define MIN(a,b) ( (a) < (b) ) ? (a) : (b)
+
+/*
+ initialize the osd rendering engine
+*/
+
+osd_renderer_t *osd_renderer_init( video_overlay_instance_t *video_overlay )
+{
+ osd_renderer_t *this;
+
+ this = xine_xmalloc(sizeof(osd_renderer_t));
+ this->video_overlay = video_overlay;
+ this->event.object.overlay = xine_xmalloc( sizeof(vo_overlay_t) );
+
+ pthread_mutex_init (&this->osd_mutex, NULL);
+
+#ifdef LOG_DEBUG
+ printf("osd_renderer_init %p\n", this);
+#endif
+
+ return this;
+}
+
+void osd_renderer_exit( osd_renderer_t *this )
+{
+
+ while( this->osds )
+ osd_close( this->osds );
+
+ while( this->fonts )
+ osd_renderer_unload_font( this, this->fonts->name );
+
+ free(this);
+}
+
+
+/*
+ open a new osd object. this will allocated an empty (all zero) drawing
+ area where graphic primitives may be used.
+ It is ok to specify big width and height values. The render will keep
+ track of the smallest changed area to not generate too big overlays.
+ A default palette is initialized (i sugest keeping color 0 as transparent
+ for the sake of simplicity)
+*/
+
+osd_object_t *osd_open(osd_renderer_t *this, int width, int height)
+{
+ osd_object_t *osd;
+
+ static clut_t default_color[] = {
+ CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00),
+ CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80),
+ CLUT_Y_CR_CB_INIT(0xff, 0x90, 0x00),
+ CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80)
+ };
+ static uint8_t default_trans[] = {0, 7, 15, 15};
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ osd = xine_xmalloc( sizeof(osd_object_t) );
+ osd->renderer = this;
+ osd->next = this->osds;
+ this->osds = osd;
+
+ osd->width = width;
+ osd->height = height;
+ osd->area = xine_xmalloc( width * height );
+
+ osd->x1 = width;
+ osd->y1 = height;
+ osd->x2 = 0;
+ osd->y2 = 0;
+
+ memcpy(osd->color, default_color, sizeof(default_color));
+ memcpy(osd->trans, default_trans, sizeof(default_trans));
+
+ osd->handle = -1;
+
+ pthread_mutex_unlock (&this->osd_mutex);
+
+#ifdef LOG_DEBUG
+ printf("osd_open %p [%dx%d]\n", osd, width, height);
+#endif
+
+ return osd;
+}
+
+
+/*
+ free osd object
+*/
+
+void osd_close(osd_object_t *osd_to_close)
+{
+ osd_renderer_t *this = osd_to_close->renderer;
+ osd_object_t *osd, *last;
+
+ if( osd_to_close->handle >= 0 )
+ osd_hide(osd_to_close,0);
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ last = NULL;
+ osd = this->osds;
+ while( osd ) {
+ if ( osd == osd_to_close ) {
+ free( osd->area );
+
+ if( last )
+ last->next = osd->next;
+ else
+ this->osds = osd->next;
+ free( osd );
+ break;
+ }
+ last = osd;
+ osd = osd->next;
+ }
+ pthread_mutex_unlock (&this->osd_mutex);
+}
+
+
+/*
+ send the osd to be displayed at given pts (0=now)
+ the object is not changed. there may be subsequent drawing on it.
+*/
+int osd_show(osd_object_t *osd, uint32_t vpts )
+{
+ osd_renderer_t *this = osd->renderer;
+ rle_elem_t rle, *rle_p=0;
+ int x, y, spare;
+ uint8_t *c;
+
+#ifdef LOG_DEBUG
+ printf("osd_show %p vpts=%d\n", osd, vpts);
+#endif
+
+ if( osd->handle >= 0 )
+ return 0; /* must hide first */
+
+ if( (osd->handle = this->video_overlay->get_handle(this->video_overlay,0)) == -1 )
+ return 0;
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ /* check if osd is valid (something draw on it) */
+ if( osd->x2 >= osd->x1 ) {
+
+ this->event.object.handle = osd->handle;
+ /* not really needed this, but good pratice to clean it up */
+ memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) );
+ this->event.object.overlay->x = osd->display_x + osd->x1;
+ this->event.object.overlay->y = osd->display_y + osd->y1;
+ this->event.object.overlay->width = osd->x2 - osd->x1 + 1;
+ this->event.object.overlay->height = osd->y2 - osd->y1 + 1;
+
+ this->event.object.overlay->clip_top = 0;
+ this->event.object.overlay->clip_bottom = this->event.object.overlay->height - 1;
+ this->event.object.overlay->clip_left = 0;
+ this->event.object.overlay->clip_right = this->event.object.overlay->width - 1;
+
+ spare = osd->y2 - osd->y1;
+
+ this->event.object.overlay->data_size = 1024;
+ rle_p = this->event.object.overlay->rle =
+ malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) );
+
+ for( y = osd->y1; y <= osd->y2; y++ ) {
+ rle.len = 0;
+ c = osd->area + y * osd->width + osd->x1;
+ for( x = osd->x1; x <= osd->x2; x++, c++ ) {
+ if( rle.color != *c ) {
+ if( rle.len ) {
+ if( (this->event.object.overlay->num_rle + spare) * sizeof(rle_elem_t) >
+ this->event.object.overlay->data_size ) {
+ this->event.object.overlay->data_size += 1024;
+ rle_p = this->event.object.overlay->rle =
+ realloc( this->event.object.overlay->rle,
+ this->event.object.overlay->data_size * sizeof(rle_elem_t) );
+ rle_p += this->event.object.overlay->num_rle;
+ }
+ *rle_p++ = rle;
+ this->event.object.overlay->num_rle++;
+ }
+ rle.color = *c;
+ rle.len = 1;
+ } else {
+ rle.len++;
+ }
+ }
+ *rle_p++ = rle;
+ this->event.object.overlay->num_rle++;
+ }
+
+#ifdef LOG_DEBUG
+ printf("osd_show num_rle = %d\n", this->event.object.overlay->num_rle);
+#endif
+
+ memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color));
+ memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans));
+
+ this->event.event_type = EVENT_SHOW_SPU;
+ this->event.vpts = vpts;
+ this->video_overlay->add_event(this->video_overlay,(void *)&this->event);
+ }
+ pthread_mutex_unlock (&this->osd_mutex);
+
+ return 1;
+}
+
+/*
+ send event to hide osd at given pts (0=now)
+ the object is not changed. there may be subsequent drawing on it.
+*/
+int osd_hide(osd_object_t *osd, uint32_t vpts )
+{
+ osd_renderer_t *this = osd->renderer;
+
+#ifdef LOG_DEBUG
+ printf("osd_hide %p vpts=%d\n",osd, vpts);
+#endif
+
+ if( osd->handle < 0 )
+ return 0;
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ this->event.object.handle = osd->handle;
+ osd->handle = -1; /* handle will be freed after hide */
+
+ /* not really needed this, but good pratice to clean it up */
+ memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) );
+
+ this->event.event_type = EVENT_HIDE_SPU;
+ this->event.vpts = vpts;
+ this->video_overlay->add_event(this->video_overlay,(void *)&this->event);
+
+ pthread_mutex_unlock (&this->osd_mutex);
+
+ return 1;
+}
+
+/*
+ Bresenham line implementation on osd object
+*/
+
+void osd_line(osd_object_t *osd,
+ int x1, int y1, int x2, int y2, int color )
+{
+ uint8_t *c;
+ int dx, dy, t, inc, d, inc1, inc2;
+
+#ifdef LOG_DEBUG
+ printf("osd_line %p (%d,%d)-(%d,%d)\n",osd, x1,y1, x2,y2 );
+#endif
+
+ /* update clipping area */
+ t = MIN( x1, x2 );
+ osd->x1 = MIN( osd->x1, t );
+ t = MAX( x1, x2 );
+ osd->x2 = MAX( osd->x2, t );
+ t = MIN( y1, y2 );
+ osd->y1 = MIN( osd->y1, t );
+ t = MAX( y1, y2 );
+ osd->y2 = MAX( osd->y2, t );
+
+ dx = abs(x1-x2);
+ dy = abs(y1-y2);
+
+ if( dx>=dy ) {
+ if( x1>x2 )
+ {
+ t = x2; x2 = x1; x1 = t;
+ t = y2; y2 = y1; y1 = t;
+ }
+
+ if( y2 > y1 ) inc = 1; else inc = -1;
+
+ inc1 = 2*dy;
+ d = inc1 - dx;
+ inc2 = 2*(dy-dx);
+
+ c = osd->area + y1 * osd->width + x1;
+
+ while(x1<x2)
+ {
+ *c++ = color;
+ x1++;
+ if( d<0 ) {
+ d+=inc1;
+ } else {
+ y1+=inc;
+ d+=inc2;
+ c = osd->area + y1 * osd->width + x1;
+ }
+ }
+ } else {
+ if( y1>y2 ) {
+ t = x2; x2 = x1; x1 = t;
+ t = y2; y2 = y1; y1 = t;
+ }
+
+ if( x2 > x1 ) inc = 1; else inc = -1;
+
+ inc1 = 2*dx;
+ d = inc1-dy;
+ inc2 = 2*(dx-dy);
+
+ c = osd->area + y1 * osd->width + x1;
+
+ while(y1<y2) {
+ *c = color;
+ c += osd->width;
+ y1++;
+ if( d<0 ) {
+ d+=inc1;
+ } else {
+ x1+=inc;
+ d+=inc2;
+ c = osd->area + y1 * osd->width + x1;
+ }
+ }
+ }
+}
+
+
+/*
+ filled retangle
+*/
+
+void osd_filled_rect(osd_object_t *osd,
+ int x1, int y1, int x2, int y2, int color )
+{
+ int x, y, dx, dy;
+
+#ifdef LOG_DEBUG
+ printf("osd_filled_rect %p (%d,%d)-(%d,%d)\n",osd, x1,y1, x2,y2 );
+#endif
+
+ /* update clipping area */
+ x = MIN( x1, x2 );
+ osd->x1 = MIN( osd->x1, x );
+ dx = MAX( x1, x2 );
+ osd->x2 = MAX( osd->x2, dx );
+ y = MIN( y1, y2 );
+ osd->y1 = MIN( osd->y1, y );
+ dy = MAX( y1, y2 );
+ osd->y2 = MAX( osd->y2, dy );
+
+ dx -= x;
+ dy -= y;
+
+ for( ; dy--; y++ ) {
+ memset(osd->area + y * osd->width + x,color,dx);
+ }
+}
+
+/*
+ set palette (color and transparency)
+*/
+
+void osd_set_palette(osd_object_t *osd, uint32_t *color, uint8_t *trans )
+{
+ memcpy(osd->color, color, sizeof(osd->color));
+ memcpy(osd->trans, trans, sizeof(osd->trans));
+}
+
+/*
+ get palette (color and transparency)
+*/
+
+void osd_get_palette(osd_object_t *osd, uint32_t *color, uint8_t *trans )
+{
+ memcpy(color, osd->color, sizeof(osd->color));
+ memcpy(trans, osd->trans, sizeof(osd->trans));
+}
+
+/*
+ set position were overlay will be blended
+*/
+
+void osd_set_position(osd_object_t *osd, int x, int y )
+{
+ osd->display_x = x;
+ osd->display_y = y;
+}
+
+static uint16_t gzread_i16(gzFile *fp) {
+ uint16_t ret;
+ ret = gzgetc(fp);
+ ret |= (gzgetc(fp)<<8);
+ return ret;
+}
+
+/*
+ load bitmap font into osd engine
+ returns the internal font name to be used with other functions
+ FIXME: check if font is already loaded!
+*/
+
+char * osd_renderer_load_font(osd_renderer_t *this, char *name)
+{
+ gzFile *fp;
+ osd_font_t *font = NULL;
+ char *filename;
+ int i, ret = 0;
+
+#ifdef LOG_DEBUG
+ printf("osd_renderer_load_font %p name=%s\n", this, name );
+#endif
+
+ filename = malloc(strlen(name)+200);
+ sprintf(filename,"%s/%s.xinefont.gz",XINE_SKINDIR, name);
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ /* load quick & dirt font format */
+ /* fixme: check read errors... */
+ if( (fp = gzopen(filename,"rb")) != NULL ) {
+
+ font = xine_xmalloc( sizeof(osd_font_t) );
+
+ gzread(fp, font->name, sizeof(font->name) );
+ font->version = gzread_i16(fp);
+ font->num_fontchars = gzread_i16(fp);
+
+ font->fontchar = malloc( sizeof(osd_fontchar_t) * font->num_fontchars );
+
+#ifdef LOG_DEBUG
+ printf("font %s %d\n",font->name, font->num_fontchars);
+#endif
+ for( i = 0; i < font->num_fontchars; i++ ) {
+ font->fontchar[i].code = gzread_i16(fp);
+ font->fontchar[i].width = gzread_i16(fp);
+ font->fontchar[i].height = gzread_i16(fp);
+ font->fontchar[i].bmp = malloc(font->fontchar[i].width*font->fontchar[i].height);
+ if( gzread(fp,font->fontchar[i].bmp,
+ font->fontchar[i].width*font->fontchar[i].height) <= 0 )
+ break;
+#ifdef LOG_DEBUG
+ printf("char[%d] %dx%d\n",font->fontchar[i].code,font->fontchar[i].width,font->fontchar[i].height);
+#endif
+ }
+
+ if( i == font->num_fontchars ) {
+ ret = 1;
+
+ font->next = this->fonts;
+ this->fonts = font;
+ } else {
+ while( --i >= 0 ) {
+ free(font->fontchar[i].bmp);
+ }
+ free(font->fontchar);
+ free(font);
+ }
+
+ gzclose(fp);
+ }
+
+ pthread_mutex_unlock (&this->osd_mutex);
+ free(filename);
+
+ if( ret )
+ return font->name;
+ else
+ return NULL;
+}
+
+/*
+ unload font
+*/
+int osd_renderer_unload_font(osd_renderer_t *this, char *fontname )
+{
+ osd_font_t *font, *last;
+ osd_object_t *osd;
+ int i, ret = 0;
+
+#ifdef LOG_DEBUG
+ printf("osd_renderer_unload_font %p name=%s\n", this, fontname);
+#endif
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ osd = this->osds;
+ while( osd ) {
+ if( !strcmp(osd->font->name, fontname) )
+ osd->font = NULL;
+ osd = osd->next;
+ }
+
+ last = NULL;
+ font = this->fonts;
+ while( font ) {
+ if ( !strcmp(font->name,fontname) ) {
+
+ for( i = 0; i < font->num_fontchars; i++ ) {
+ free( font->fontchar[i].bmp );
+ }
+ free( font->fontchar );
+
+ if( last )
+ last->next = font->next;
+ else
+ this->fonts = font->next;
+ free( font );
+ break;
+ }
+ last = font;
+ font = font->next;
+ }
+
+ pthread_mutex_unlock (&this->osd_mutex);
+ return ret;
+}
+
+
+/*
+ set the font of osd object
+*/
+
+int osd_set_font( osd_object_t *osd, char *fontname )
+{
+ osd_renderer_t *this = osd->renderer;
+ osd_font_t *font;
+ int ret = 0;
+
+#ifdef LOG_DEBUG
+ printf("osd_set_font %p name=%s\n", osd, fontname);
+#endif
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ osd->font = NULL;
+
+ font = this->fonts;
+ while( font ) {
+ if( !strcmp(font->name, fontname) ) {
+ ret = 1;
+ osd->font = font;
+ }
+ font = font->next;
+ }
+
+ pthread_mutex_unlock (&this->osd_mutex);
+ return ret;
+}
+
+
+/*
+ render text on x,y position (8 bits version)
+ no \n yet
+*/
+int osd_render_text( osd_object_t *osd, int x1, int y1, char *text )
+{
+ osd_renderer_t *this = osd->renderer;
+ osd_font_t *font;
+ int i, y;
+ uint8_t *dst, *src;
+
+#ifdef LOG_DEBUG
+ printf("osd_render_text %p (%d,%d) \"%s\"\n", osd, x1, y1, text);
+#endif
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ font = osd->font;
+
+ if( x1 < osd->x1 ) osd->x1 = x1;
+ if( y1 < osd->y1 ) osd->y1 = y1;
+
+ while( font && *text ) {
+
+ for( i = 0; i < font->num_fontchars; i++ ) {
+ if( font->fontchar[i].code == (*text & 0xff) )
+ break;
+ }
+
+#ifdef LOG_DEBUG
+ printf("font %s [%d] %dx%d -> %d,%d\n",font->name, *text,
+ font->fontchar[i].width, font->fontchar[i].height,
+ x1,y1);
+#endif
+
+ if ( i != font->num_fontchars ) {
+ dst = osd->area + y1 * osd->width + x1;
+ src = font->fontchar[i].bmp;
+
+ for( y = 0; y < font->fontchar[i].height; y++ ) {
+ memcpy( dst, src, font->fontchar[i].width );
+ src += font->fontchar[i].width;
+ dst += osd->width;
+ }
+ x1 += font->fontchar[i].width;
+
+ if( x1 > osd->x2 ) osd->x2 = x1;
+ if( y1 + font->fontchar[i].height > osd->y2 )
+ osd->y2 = y1 + font->fontchar[i].height;
+ }
+ text++;
+ }
+
+ pthread_mutex_unlock (&this->osd_mutex);
+
+ return 1;
+}
+
+/*
+ get width and height of how text will be renderized
+*/
+int osd_get_text_size( osd_object_t *osd, char *text, int *width, int *height )
+{
+ osd_renderer_t *this = osd->renderer;
+ osd_font_t *font;
+ int i;
+
+#ifdef LOG_DEBUG
+ printf("osd_get_text_size %p \"%s\"\n", osd, text);
+#endif
+
+ pthread_mutex_lock (&this->osd_mutex);
+
+ font = osd->font;
+
+ *width = 0;
+ *height = 0;
+
+ while( *text ) {
+
+ for( i = 0; i < font->num_fontchars; i++ ) {
+ if( font->fontchar[i].code == *text )
+ break;
+ }
+
+ if ( i != font->num_fontchars ) {
+ if( font->fontchar[i].height > *height )
+ *height = font->fontchar[i].height;
+ *width += font->fontchar[i].width;
+ }
+ text++;
+ }
+
+ pthread_mutex_unlock (&this->osd_mutex);
+
+ return 1;
+}
+
diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h
new file mode 100644
index 000000000..2e27faf93
--- /dev/null
+++ b/src/xine-engine/osd.h
@@ -0,0 +1,159 @@
+#ifndef __OSD_H__
+#define __OSD_H__
+
+#ifdef __OSD_C__
+
+typedef struct osd_object_s osd_object_t;
+typedef struct osd_renderer_s osd_renderer_t;
+typedef struct osd_fontchar_s osd_fontchar_t;
+typedef struct osd_font_s osd_font_t;
+
+struct osd_object_s {
+ osd_object_t *next;
+ osd_renderer_t *renderer;
+
+ int width, height; /* work area dimentions */
+ uint8_t *area; /* work area */
+ int display_x,display_y; /* where to display it in screen */
+
+ /* clipping box inside work area */
+ int x1, y1;
+ int x2, y2;
+
+ uint32_t color[16]; /* color lookup table */
+ uint8_t trans[16]; /* mixer key table */
+
+ int32_t handle;
+
+ osd_font_t *font;
+};
+
+
+struct osd_renderer_s {
+ pthread_mutex_t osd_mutex;
+ video_overlay_instance_t *video_overlay;
+ video_overlay_event_t event;
+ osd_object_t *osds;
+ osd_font_t *fonts;
+};
+
+struct osd_fontchar_s {
+ uint16_t code;
+ uint16_t width;
+ uint16_t height;
+ uint8_t *bmp;
+};
+
+struct osd_font_s {
+ char name[40];
+ uint16_t version;
+ uint16_t num_fontchars;
+ osd_fontchar_t *fontchar;
+ osd_font_t *next;
+};
+
+#else
+
+typedef void osd_object_t;
+typedef void osd_renderer_t;
+
+#endif
+
+/*
+ initialize the osd rendering engine
+*/
+osd_renderer_t *osd_renderer_init( video_overlay_instance_t *video_overlay );
+
+/* close osd rendering engine
+ loaded fonts are unloaded
+ osd objects are closed
+*/
+void osd_renderer_exit( osd_renderer_t *this );
+
+/*
+ open a new osd object. this will allocated an empty (all zero) drawing
+ area where graphic primitives may be used.
+ It is ok to specify big width and height values. The render will keep
+ track of the smallest changed area to not generate too big overlays.
+ A default palette is initialized (i sugest keeping color 0 as transparent
+ for the sake of simplicity)
+*/
+osd_object_t *osd_open(osd_renderer_t *this, int width, int height);
+
+
+/*
+ free osd object
+*/
+void osd_close(osd_object_t *osd_to_close);
+
+
+/*
+ send the osd to be displayed at given pts (0=now)
+ the object is not changed. there may be subsequent drawing on it.
+*/
+int osd_show(osd_object_t *osd, uint32_t vpts );
+
+/*
+ send event to hide osd at given pts (0=now)
+ the object is not changed. there may be subsequent drawing on it.
+*/
+int osd_hide(osd_object_t *osd, uint32_t vpts );
+
+/*
+ Bresenham line implementation on osd object
+*/
+void osd_line(osd_object_t *osd,
+ int x1, int y1, int x2, int y2, int color );
+
+/*
+ filled retangle
+*/
+void osd_filled_rect(osd_object_t *osd,
+ int x1, int y1, int x2, int y2, int color );
+
+/*
+ set palette (color and transparency)
+*/
+void osd_set_palette(osd_object_t *osd, uint32_t *color, uint8_t *trans );
+
+/*
+ get palette (color and transparency)
+*/
+void osd_get_palette(osd_object_t *osd, uint32_t *color, uint8_t *trans );
+
+/*
+ set position were overlay will be blended
+*/
+void osd_set_position(osd_object_t *osd, int x, int y );
+
+/*
+ load bitmap font into osd engine
+*/
+char * osd_renderer_load_font(osd_renderer_t *this, char *name);
+
+/*
+ unload font
+*/
+int osd_renderer_unload_font(osd_renderer_t *this, char *name );
+
+/*
+ set the font of osd object
+*/
+
+int osd_set_font( osd_object_t *osd, char *fontname );
+
+
+/*
+ render text on x,y position (8 bits version)
+ no \n yet
+*/
+int osd_render_text( osd_object_t *osd, int x1, int y1, char *text );
+
+/*
+ get width and height of how text will be renderized
+*/
+int osd_get_text_size( osd_object_t *osd, char *text, int *width, int *height );
+
+
+#endif
+
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 920b69577..b4acb22ad 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.c,v 1.57 2001/11/20 12:41:58 miguelfreitas Exp $
+ * $Id: video_out.c,v 1.58 2001/11/28 22:19:12 miguelfreitas Exp $
*
*/
@@ -297,16 +297,13 @@ static void *video_out_loop (void *this_gen) {
#endif
if (this->overlay_source) {
- /* This is the only way for the spu decoder to get pts values
+ /* This is the only way for the overlay manager to get pts values
* for flushing it's buffers. So don't remove it! */
- vo_overlay_t *ovl;
-
xine_profiler_start_count (prof_spu_blend);
- ovl = this->overlay_source->get_overlay (this->overlay_source, img->PTS);
- if (this->video_loop_running && ovl && this->driver->overlay_blend && this->overlay_enabled)
- this->driver->overlay_blend (this->driver, img, ovl);
-
+ this->overlay_source->multiple_overlay_blend (this->overlay_source, img->PTS,
+ this->driver, img,
+ this->video_loop_running && this->overlay_enabled);
xine_profiler_stop_count (prof_spu_blend);
}
@@ -408,7 +405,11 @@ static vo_frame_t *vo_get_frame (vo_instance_t *this,
}
static void vo_close (vo_instance_t *this) {
-
+
+ /* this will make sure all hide events were processed */
+ if (this->overlay_source)
+ this->overlay_source->flush_events (this->overlay_source);
+
if (this->video_loop_running) {
void *p;
@@ -570,19 +571,6 @@ static int vo_frame_draw (vo_frame_t *img) {
return frames_to_skip;
}
-static void vo_register_ovl_src (vo_instance_t *this, ovl_src_t *ovl_src)
-{
- this->overlay_source = ovl_src;
- ovl_src->metronom = this->metronom;
-}
-
-static void vo_unregister_ovl_src (vo_instance_t *this, ovl_src_t *ovl_src)
-{
- /* only remove the source if it is the same as registered */
- if (this->overlay_source == ovl_src)
- this->overlay_source = NULL;
-}
-
static void vo_enable_overlay (vo_instance_t *this, int overlay_enabled) {
this->overlay_enabled = overlay_enabled;
}
@@ -602,8 +590,6 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) {
this->close = vo_close;
this->exit = vo_exit;
this->get_capabilities = vo_get_capabilities;
- this->register_ovl_src = vo_register_ovl_src;
- this->unregister_ovl_src = vo_unregister_ovl_src;
this->enable_ovl = vo_enable_overlay;
this->num_frames_delivered = 0;
@@ -612,9 +598,12 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) {
this->free_img_buf_queue = vo_new_img_buf_queue ();
this->display_img_buf_queue = vo_new_img_buf_queue ();
this->video_loop_running = 0;
- this->video_paused = 0;
+ this->video_paused = 0;
this->pts_per_frame = 0;
this->pts_per_half_frame = 0;
+
+ this->overlay_source = video_overlay_new_instance();
+ this->overlay_source->init (this->overlay_source);
this->overlay_enabled = 1;
for (i=0; i<NUM_FRAME_BUFFERS; i++) {
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index 8e4ac0828..4f0acf681 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.h,v 1.30 2001/11/20 12:41:58 miguelfreitas Exp $
+ * $Id: video_out.h,v 1.31 2001/11/28 22:19:12 miguelfreitas Exp $
*
*
* xine version of video_out.h
@@ -53,6 +53,7 @@ typedef struct vo_driver_s vo_driver_t ;
typedef struct vo_instance_s vo_instance_t;
typedef struct img_buf_fifo_s img_buf_fifo_t;
typedef struct vo_overlay_s vo_overlay_t;
+typedef struct video_overlay_instance_s video_overlay_instance_t;
/* public part, video drivers may add private fields */
@@ -99,14 +100,6 @@ struct vo_frame_s {
void (*dispose) (vo_frame_t *vo_img);
};
-typedef struct ovl_src_s ovl_src_t;
-
-struct ovl_src_s {
- void *src_gen;
- vo_overlay_t* (*get_overlay) (ovl_src_t* self, int pts);
- metronom_t* metronom;
-};
-
struct vo_instance_s {
uint32_t (*get_capabilities) (vo_instance_t *this); /* for constants see below */
@@ -132,11 +125,9 @@ struct vo_instance_s {
vo_frame_t* (*get_last_frame) (vo_instance_t *this);
/* overlay stuff */
- void (*register_ovl_src) (vo_instance_t *this, ovl_src_t *ovl_src);
- void (*unregister_ovl_src) (vo_instance_t *this, ovl_src_t *ovl_src);
void (*enable_ovl) (vo_instance_t *this, int ovl_enable);
- ovl_src_t *overlay_source;
- int overlay_enabled;
+ video_overlay_instance_t *overlay_source;
+ int overlay_enabled;
/* video driver is no longer used by decoder => close */
void (*close) (vo_instance_t *this);
@@ -308,8 +299,8 @@ struct vo_overlay_s {
int width; /* width of subpicture area */
int height; /* height of subpicture area */
- uint32_t color[4]; /* color lookup table */
- uint8_t trans[4]; /* mixer key table */
+ uint32_t color[16]; /* color lookup table */
+ uint8_t trans[16]; /* mixer key table */
int rgb_clut; /* true if clut was converted to rgb*/
int clip_top;
@@ -319,6 +310,26 @@ struct vo_overlay_s {
};
+
+/* API to video_overlay */
+struct video_overlay_instance_s {
+ void (*init) (video_overlay_instance_t *this_gen);
+
+ int32_t (*get_handle) (video_overlay_instance_t *this_gen, int object_type );
+
+ void (*free_handle) (video_overlay_instance_t *this_gen, int32_t handle);
+
+ int32_t (*add_event) (video_overlay_instance_t *this_gen, void *event);
+
+ void (*flush_events) (video_overlay_instance_t *this_gen );
+
+ void (*multiple_overlay_blend) (video_overlay_instance_t *this_gen, int vpts,
+ vo_driver_t *output, vo_frame_t *vo_img, int enabled);
+};
+
+video_overlay_instance_t *video_overlay_new_instance ();
+
+
/*
* build a video_out_instance from
* a given video driver
diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c
new file mode 100644
index 000000000..099f0416b
--- /dev/null
+++ b/src/xine-engine/video_overlay.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine 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.
+ *
+ * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: video_overlay.c,v 1.1 2001/11/28 22:19:11 miguelfreitas Exp $
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "buffer.h"
+#include "events.h"
+#include "xine_internal.h"
+#include "video_out/alphablend.h"
+#include "xine-engine/bswap.h"
+#include "xineutils.h"
+#include "video_overlay.h"
+
+/*
+#define LOG_DEBUG 1
+*/
+
+
+typedef struct video_overlay_events_s {
+ video_overlay_event_t *event;
+ uint32_t next_event;
+} video_overlay_events_t;
+
+typedef struct video_overlay_showing_s {
+ int32_t handle; /* -1 means not allocated */
+} video_overlay_showing_t;
+
+
+typedef struct video_overlay_s {
+ video_overlay_instance_t video_overlay;
+
+ pthread_mutex_t video_overlay_events_mutex;
+ video_overlay_events_t video_overlay_events[MAX_EVENTS];
+ pthread_mutex_t video_overlay_objects_mutex;
+ video_overlay_object_t video_overlay_objects[MAX_OBJECTS];
+ pthread_mutex_t video_overlay_showing_mutex;
+ video_overlay_showing_t video_overlay_showing[MAX_SHOWING];
+
+} video_overlay_t;
+
+
+static void add_showing_handle( video_overlay_t *this, int32_t handle )
+{
+ int i;
+
+ pthread_mutex_lock( &this->video_overlay_showing_mutex );
+
+ for( i = 0; i < MAX_SHOWING; i++ )
+ if( this->video_overlay_showing[i].handle == handle )
+ break; /* already showing */
+
+ if( i == MAX_SHOWING ) {
+ for( i = 0; i < MAX_SHOWING && this->video_overlay_showing[i].handle >= 0; i++ )
+ ;
+
+ if( i != MAX_SHOWING )
+ this->video_overlay_showing[i].handle = handle;
+ else
+ fprintf(stderr,"video_overlay: error: no showing slots available\n");
+ }
+
+ pthread_mutex_unlock( &this->video_overlay_showing_mutex );
+}
+
+static void remove_showing_handle( video_overlay_t *this, int32_t handle )
+{
+ int i;
+
+ pthread_mutex_lock( &this->video_overlay_showing_mutex );
+
+ for( i = 0; i < MAX_SHOWING; i++ ) {
+ if( this->video_overlay_showing[i].handle == handle ) {
+ this->video_overlay_showing[i].handle = -1;
+ }
+ }
+
+ pthread_mutex_unlock( &this->video_overlay_showing_mutex );
+}
+
+static void remove_events_handle( video_overlay_t *this, int32_t handle )
+{
+ uint32_t last_event,this_event;
+
+ pthread_mutex_lock( &this->video_overlay_events_mutex );
+
+ this_event=0;
+ do {
+ last_event=this_event;
+ this_event=this->video_overlay_events[last_event].next_event;
+
+ while( this_event &&
+ this->video_overlay_events[this_event].event->object.handle == handle ) {
+ /* remove event from pts list */
+ this->video_overlay_events[last_event].next_event=
+ this->video_overlay_events[this_event].next_event;
+
+ /* free its overlay */
+ if( this->video_overlay_events[this_event].event->object.overlay ) {
+ if( this->video_overlay_events[this_event].event->object.overlay->rle )
+ free( this->video_overlay_events[this_event].event->object.overlay->rle );
+ free(this->video_overlay_events[this_event].event->object.overlay);
+ this->video_overlay_events[this_event].event->object.overlay = NULL;
+ }
+
+ /* mark as free */
+ this->video_overlay_events[this_event].next_event = 0;
+ this->video_overlay_events[this_event].event->event_type = EVENT_NULL;
+
+ this_event=this->video_overlay_events[last_event].next_event;
+ }
+ } while ( this_event );
+
+ pthread_mutex_unlock( &this->video_overlay_events_mutex );
+}
+
+
+/*
+ allocate a handle from the object pool (exported function)
+ */
+static int32_t video_overlay_get_handle(video_overlay_instance_t *this_gen, int object_type ) {
+ video_overlay_t *this = (video_overlay_t *) this_gen;
+ int n;
+
+ pthread_mutex_lock( &this->video_overlay_objects_mutex );
+
+ for( n=0; n < MAX_OBJECTS && this->video_overlay_objects[n].handle > -1; n++ )
+ ;
+
+ if (n == MAX_OBJECTS) {
+ n = -1;
+ } else {
+ this->video_overlay_objects[n].handle = n;
+ this->video_overlay_objects[n].object_type = object_type;
+ }
+
+ pthread_mutex_unlock( &this->video_overlay_objects_mutex );
+ return n;
+}
+
+/*
+ free a handle from the object pool (internal function)
+ */
+static void internal_video_overlay_free_handle(video_overlay_t *this, int32_t handle) {
+
+ pthread_mutex_lock( &this->video_overlay_objects_mutex );
+
+ if( this->video_overlay_objects[handle].overlay ) {
+ if( this->video_overlay_objects[handle].overlay->rle )
+ free( this->video_overlay_objects[handle].overlay->rle );
+ free( this->video_overlay_objects[handle].overlay );
+ this->video_overlay_objects[handle].overlay = NULL;
+ }
+ this->video_overlay_objects[handle].handle = -1;
+
+ pthread_mutex_unlock( &this->video_overlay_objects_mutex );
+}
+
+/*
+ exported free handle function. must take care of removing the object
+ from showing and events lists.
+*/
+static void video_overlay_free_handle(video_overlay_instance_t *this_gen, int32_t handle) {
+ video_overlay_t *this = (video_overlay_t *) this_gen;
+
+ remove_showing_handle(this,handle);
+ remove_events_handle(this,handle);
+ internal_video_overlay_free_handle(this,handle);
+}
+
+
+
+static void video_overlay_reset (video_overlay_t *this) {
+ int i;
+
+ pthread_mutex_lock (&this->video_overlay_events_mutex);
+ for (i=0; i < MAX_EVENTS; i++) {
+ if (this->video_overlay_events[i].event == NULL) {
+ this->video_overlay_events[i].event = xine_xmalloc (sizeof(video_overlay_event_t));
+#ifdef LOG_DEBUG
+ printf ("video_overlay: MALLOC2: this->video_overlay_events[%d].event %p, len=%d\n",
+ i,
+ this->video_overlay_events[i].event,
+ sizeof(video_overlay_event_t));
+#endif
+ }
+ this->video_overlay_events[i].event->event_type = 0; /* Empty slot */
+ this->video_overlay_events[i].next_event = 0;
+ }
+ pthread_mutex_unlock (&this->video_overlay_events_mutex);
+
+ for (i=0; i < MAX_OBJECTS; i++) {
+ internal_video_overlay_free_handle(this, i);
+ }
+
+ for( i = 0; i < MAX_SHOWING; i++ )
+ this->video_overlay_showing[i].handle = -1;
+}
+
+
+static void video_overlay_init (video_overlay_instance_t *this_gen) {
+
+ video_overlay_t *this = (video_overlay_t *) this_gen;
+
+ pthread_mutex_init (&this->video_overlay_events_mutex,NULL);
+ pthread_mutex_init (&this->video_overlay_objects_mutex,NULL);
+ pthread_mutex_init (&this->video_overlay_showing_mutex,NULL);
+
+ video_overlay_reset(this);
+}
+
+
+/* add an event to the events queue, sort the queue based on vpts.
+ * This can be the API entry point for DVD subtitles.
+ * One calls this function with an event, the event contains an overlay
+ * and a vpts when to action/process it. vpts of 0 means action the event now.
+ * One also has a handle, so one can match show and hide events.
+ *
+ * note: on success event->object.overlay is "taken" (caller will not have access
+ * to overlay data including rle).
+ * note2: handle will be freed on HIDE events
+ */
+static int32_t video_overlay_add_event(video_overlay_instance_t *this_gen, void *event_gen ) {
+ video_overlay_event_t *event = (video_overlay_event_t *) event_gen;
+ video_overlay_t *this = (video_overlay_t *) this_gen;
+ uint32_t last_event,this_event,new_event;
+
+ pthread_mutex_lock (&this->video_overlay_events_mutex);
+
+ /* We skip the 0 entry because that is used as a pointer to the first event.*/
+ /* Find a free event slot */
+ for( new_event = 1; new_event<MAX_EVENTS &&
+ this->video_overlay_events[new_event].event->event_type > 0; new_event++ )
+ ;
+
+ if (new_event < MAX_EVENTS) {
+ /* Find position in event queue to be added. */
+ this_event=0;
+ /* Find where in the current queue to insert the event. I.E. Sort it. */
+ do {
+ last_event=this_event;
+ this_event=this->video_overlay_events[last_event].next_event;
+ } while ( this_event && this->video_overlay_events[this_event].event->vpts < event->vpts );
+
+ this->video_overlay_events[last_event].next_event=new_event;
+ this->video_overlay_events[new_event].next_event=this_event;
+
+ /* memcpy everything except the actual image */
+ if ( this->video_overlay_events[new_event].event == NULL ) {
+ fprintf(stderr,"video_overlay: error: event slot is NULL!\n");
+ }
+ this->video_overlay_events[new_event].event->event_type=event->event_type;
+ this->video_overlay_events[new_event].event->vpts=event->vpts;
+ this->video_overlay_events[new_event].event->object.handle=event->object.handle;
+
+ if ( this->video_overlay_events[new_event].event->object.overlay ) {
+ fprintf(stderr,"video_overlay: error: event->object.overlay was not freed!\n");
+ }
+
+ this->video_overlay_events[new_event].event->object.overlay = xine_xmalloc (sizeof(vo_overlay_t));
+ memcpy(this->video_overlay_events[new_event].event->object.overlay,
+ event->object.overlay, sizeof(vo_overlay_t));
+
+ /* We took the callers rle and data, therefore it will be our job to free it */
+ /* clear callers overlay so it will not be freed twice */
+ memset(event->object.overlay,0,sizeof(vo_overlay_t));
+ } else {
+ fprintf(stderr, "No spare subtitle event slots\n");
+ new_event = -1;
+ }
+
+ pthread_mutex_unlock (&this->video_overlay_events_mutex);
+
+ return new_event;
+}
+
+
+/* not currently used. James might need this for debugging menu stuff */
+static void video_overlay_print_overlay( vo_overlay_t *ovl ) {
+#ifdef LOG_DEBUG
+ printf ("video_overlay: OVERLAY to show\n");
+ printf ("video_overlay: \tx = %d y = %d width = %d height = %d\n",
+ ovl->x, ovl->y, ovl->width, ovl->height );
+ printf ("video_overlay: \tclut [%x %x %x %x]\n",
+ ovl->color[0], ovl->color[1], ovl->color[2], ovl->color[3]);
+ printf ("video_overlay: \ttrans [%d %d %d %d]\n",
+ ovl->trans[0], ovl->trans[1], ovl->trans[2], ovl->trans[3]);
+ printf ("video_overlay: \tclip top=%d bottom=%d left=%d right=%d\n",
+ ovl->clip_top, ovl->clip_bottom, ovl->clip_left, ovl->clip_right);
+#endif
+ return;
+}
+
+/*
+ process overlay events
+ if vpts == 0 will process everything now (used in flush)
+*/
+static void video_overlay_event( video_overlay_t *this, int vpts ) {
+ int32_t handle;
+ uint32_t this_event;
+
+ pthread_mutex_lock (&this->video_overlay_events_mutex);
+
+ this_event=this->video_overlay_events[0].next_event;
+ while ( this_event && (vpts > this->video_overlay_events[this_event].event->vpts ||
+ vpts == 0) ) {
+ handle=this->video_overlay_events[this_event].event->object.handle;
+ switch( this->video_overlay_events[this_event].event->event_type ) {
+ case EVENT_SHOW_SPU:
+#ifdef LOG_DEBUG
+ printf ("video_overlay: SHOW SPU NOW\n");
+#endif
+ if (this->video_overlay_events[this_event].event->object.overlay != NULL) {
+ internal_video_overlay_free_handle( this, handle );
+
+ this->video_overlay_objects[handle].handle = handle;
+ if( this->video_overlay_objects[handle].overlay ) {
+ fprintf(stderr,"video_overlay: error: object->overlay was not freed!\n");
+ }
+ this->video_overlay_objects[handle].overlay =
+ this->video_overlay_events[this_event].event->object.overlay;
+ this->video_overlay_events[this_event].event->object.overlay = NULL;
+
+ add_showing_handle( this, handle );
+ }
+ break;
+
+ /* implementation for HIDE_SPU and HIDE_MENU is the same.
+ i will keep them separated in case we need something special...
+ */
+ case EVENT_HIDE_SPU:
+#ifdef LOG_DEBUG
+ printf ("video_overlay: HIDE SPU NOW\n");
+#endif
+ free(this->video_overlay_events[this_event].event->object.overlay);
+ this->video_overlay_events[this_event].event->object.overlay = NULL;
+ remove_showing_handle( this, handle );
+ internal_video_overlay_free_handle( this, handle );
+ break;
+
+ case EVENT_HIDE_MENU:
+#ifdef LOG_DEBUG
+ printf ("video_overlay: HIDE MENU NOW %d\n",handle);
+#endif
+ free(this->video_overlay_events[this_event].event->object.overlay);
+ this->video_overlay_events[this_event].event->object.overlay = NULL;
+ remove_showing_handle( this, handle );
+ internal_video_overlay_free_handle( this, handle );
+ break;
+
+ case EVENT_MENU_SPU:
+ /* mixes palette and copy rle */
+#ifdef LOG_DEBUG
+ printf ("MENU SPU NOW\n");
+#endif
+ if (this->video_overlay_events[this_event].event->object.overlay != NULL) {
+ vo_overlay_t *event_overlay = this->video_overlay_events[this_event].event->object.overlay;
+ vo_overlay_t *overlay;
+
+ /* we need to allocate overlay on first EVENT_MENU_SPU */
+ if( !this->video_overlay_objects[handle].overlay ) {
+ this->video_overlay_objects[handle].overlay
+ = xine_xmalloc( sizeof(vo_overlay_t) );
+ }
+ overlay = this->video_overlay_objects[handle].overlay;
+
+ this->video_overlay_objects[handle].handle = handle;
+
+ /* If rle is not empty, free it first */
+ if(overlay->rle) {
+ free (overlay->rle);
+ }
+ overlay->rle = event_overlay->rle;
+
+ overlay->data_size = event_overlay->data_size;
+ overlay->num_rle = event_overlay->num_rle;
+ overlay->x = event_overlay->x;
+ overlay->y = event_overlay->y;
+ overlay->width = event_overlay->width;
+ overlay->height = event_overlay->height;
+ overlay->rgb_clut = event_overlay->rgb_clut;
+ if((event_overlay->color[0] +
+ event_overlay->color[1] +
+ event_overlay->color[2] +
+ event_overlay->color[3]) > 0 ) {
+ overlay->color[0] = event_overlay->color[0];
+ overlay->color[1] = event_overlay->color[1];
+ overlay->color[2] = event_overlay->color[2];
+ overlay->color[3] = event_overlay->color[3];
+ }
+ if((event_overlay->trans[0] +
+ event_overlay->trans[1] +
+ event_overlay->trans[2] +
+ event_overlay->trans[3]) > 0 ) {
+ overlay->trans[0] = event_overlay->trans[0];
+ overlay->trans[1] = event_overlay->trans[1];
+ overlay->trans[2] = event_overlay->trans[2];
+ overlay->trans[3] = event_overlay->trans[3];
+ }
+ add_showing_handle( this, handle );
+
+ /* The null test was done at the start of this case statement */
+ free (this->video_overlay_events[this_event].event->object.overlay);
+ this->video_overlay_events[this_event].event->object.overlay = NULL;
+ }
+ break;
+
+ case EVENT_MENU_BUTTON:
+ /* mixes palette and copy clip coords */
+#ifdef LOG_DEBUG
+ printf ("MENU BUTTON NOW\n");
+#endif
+ if (this->video_overlay_events[this_event].event->object.overlay != NULL) {
+ vo_overlay_t *overlay = this->video_overlay_objects[handle].overlay;
+ vo_overlay_t *event_overlay = this->video_overlay_events[this_event].event->object.overlay;
+
+ if( !this->video_overlay_objects[handle].overlay ) {
+ fprintf(stderr,"video_overlay: error: button event received and no overlay allocated.\n");
+ }
+
+ this->video_overlay_objects[handle].handle = handle;
+ overlay->clip_top = event_overlay->clip_top;
+ overlay->clip_bottom = event_overlay->clip_bottom;
+ overlay->clip_left = event_overlay->clip_left;
+ overlay->clip_right = event_overlay->clip_right;
+
+ if((event_overlay->color[0] +
+ event_overlay->color[1] +
+ event_overlay->color[2] +
+ event_overlay->color[3]) > 0 ) {
+ overlay->color[0] = event_overlay->color[0];
+ overlay->color[1] = event_overlay->color[1];
+ overlay->color[2] = event_overlay->color[2];
+ overlay->color[3] = event_overlay->color[3];
+ }
+ if((event_overlay->trans[0] +
+ event_overlay->trans[1] +
+ event_overlay->trans[2] +
+ event_overlay->trans[3]) > 0 ) {
+ overlay->trans[0] = event_overlay->trans[0];
+ overlay->trans[1] = event_overlay->trans[1];
+ overlay->trans[2] = event_overlay->trans[2];
+ overlay->trans[3] = event_overlay->trans[3];
+ }
+ add_showing_handle( this, handle );
+
+ if( this->video_overlay_events[this_event].event->object.overlay->rle ) {
+ printf ("video_overlay: warning EVENT_MENU_BUTTON with rle data\n");
+ free( this->video_overlay_events[this_event].event->object.overlay->rle );
+ }
+
+ /* The null test was done at the start of this case statement */
+ free (this->video_overlay_events[this_event].event->object.overlay);
+ this->video_overlay_events[this_event].event->object.overlay = NULL;
+ }
+ break;
+
+ default:
+ printf ("video_overlay: unhandled event type\n");
+ break;
+ }
+
+ this->video_overlay_events[0].next_event = this->video_overlay_events[this_event].next_event;
+ this->video_overlay_events[this_event].next_event = 0;
+ this->video_overlay_events[this_event].event->event_type = 0;
+
+ this_event=this->video_overlay_events[0].next_event;
+ }
+
+ pthread_mutex_unlock (&this->video_overlay_events_mutex);
+}
+
+/* This is called from video_out.c
+ * must call output->overlay_blend for each active overlay.
+ */
+static void video_overlay_multiple_overlay_blend(video_overlay_instance_t *this_gen, int vpts,
+ vo_driver_t *output, vo_frame_t *vo_img, int enabled) {
+ video_overlay_t *this = (video_overlay_t *) this_gen;
+ int i;
+ int32_t handle;
+
+ /* Look at next events, if current video vpts > first event on queue, process the event
+ * else just continue
+ */
+ video_overlay_event( this, vpts );
+
+ /* Scan through 5 entries and display any present.
+ */
+ pthread_mutex_lock( &this->video_overlay_showing_mutex );
+ for( i = 0; enabled && output->overlay_blend && i < MAX_SHOWING; i++ ) {
+ handle=this->video_overlay_showing[i].handle;
+ if (handle >= 0 ) {
+ output->overlay_blend(output, vo_img, this->video_overlay_objects[handle].overlay);
+ }
+ }
+ pthread_mutex_unlock( &this->video_overlay_showing_mutex );
+}
+
+
+/* this should be called on stream end or stop to make sure every
+ hide event is processed.
+*/
+static void video_overlay_flush_events(video_overlay_instance_t *this_gen )
+{
+ video_overlay_t *this = (video_overlay_t *) this_gen;
+
+ video_overlay_event( this, 0 );
+}
+
+
+video_overlay_instance_t *video_overlay_new_instance () {
+
+ video_overlay_t *this;
+
+ this = (video_overlay_t *) xine_xmalloc (sizeof (video_overlay_t));
+
+ this->video_overlay.init = video_overlay_init;
+ this->video_overlay.get_handle = video_overlay_get_handle;
+ this->video_overlay.free_handle = video_overlay_free_handle;
+ this->video_overlay.add_event = video_overlay_add_event;
+ this->video_overlay.flush_events = video_overlay_flush_events;
+ this->video_overlay.multiple_overlay_blend = video_overlay_multiple_overlay_blend;
+
+ return (video_overlay_instance_t *) &this->video_overlay;
+}
+
diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h
new file mode 100644
index 000000000..6cd3c4670
--- /dev/null
+++ b/src/xine-engine/video_overlay.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2000-2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine 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.
+ *
+ * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: video_overlay.h,v 1.1 2001/11/28 22:19:11 miguelfreitas Exp $
+ *
+ */
+
+#include "xine_internal.h"
+#include "video_out/alphablend.h"
+#include "xine-engine/bswap.h"
+
+#ifdef __GNUC__
+#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) {y: (_y), cr: (_cr), cb: (_cb)}
+#else
+#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) }
+#endif
+
+#define MAX_OBJECTS 50
+#define MAX_EVENTS 50
+#define MAX_SHOWING 5
+
+#define EVENT_NULL 0
+#define EVENT_SHOW_SPU 1
+#define EVENT_HIDE_SPU 2
+#define EVENT_HIDE_MENU 3
+#define EVENT_MENU_SPU 4
+#define EVENT_MENU_BUTTON 5
+#define EVENT_DELETE_RESOURCE 6 /* Maybe release handle will do this */
+#define EVENT_SHOW_OSD 7 /* Not yet implemented */
+
+typedef struct video_overlay_object_s {
+ int32_t handle; /* Used to match Show and Hide events. */
+ uint32_t object_type; /* 0=Subtitle, 1=Menu */
+ uint32_t pts; /* Needed for Menu button compares */
+ vo_overlay_t *overlay; /* The image data. */
+ uint32_t palette_type; /* 1 Y'CrCB, 2 R'G'B' */
+ uint32_t *palette; /* If NULL, no palette contained in this event. */
+} video_overlay_object_t;
+
+/* This will hold all details of an event item, needed for event queue to function */
+typedef struct video_overlay_event_s {
+ uint32_t event_type; /* Show SPU, Show OSD, Hide etc. */
+ uint32_t vpts; /* Time when event will action. 0 means action now */
+/* Once video_out blend_yuv etc. can take rle_elem_t with Colour, blend and length information.
+ * we can remove clut and blend from this structure.
+ * This will allow for many more colours for OSD.
+ */
+ video_overlay_object_t object; /* The image data. */
+} video_overlay_event_t;
+
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 5c182f7f2..f15eed2eb 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine.c,v 1.80 2001/11/24 23:52:40 miguelfreitas Exp $
+ * $Id: xine.c,v 1.81 2001/11/28 22:19:12 miguelfreitas Exp $
*
* top-level xine functions
*
@@ -50,6 +50,7 @@
#include "input/input_plugin.h"
#include "metronom.h"
#include "configfile.h"
+#include "osd.h"
#include "xineutils.h"
@@ -434,7 +435,19 @@ xine_t *xine_init (vo_driver_t *vo,
this->video_out = vo_new_instance (vo, this->metronom);
video_decoder_init (this);
-
+ this->osd_renderer = osd_renderer_init( this->video_out->overlay_source );
+ osd_renderer_load_font( this->osd_renderer, "vga" );
+
+ /* just kidding. this will be removed before 0.9.7 */
+ {
+ osd_object_t *osd;
+ osd = osd_open(this->osd_renderer, 120, 120);
+ osd_set_font(osd,"vga");
+ osd_render_text(osd,0,0,"\x0ff");
+ osd_set_position(osd,10,10);
+ osd_show(osd,0);
+ }
+
if(ao)
this->audio_out = ao_new_instance (ao, this->metronom, config);
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 118ee0950..5fdc58f3b 100644
--- a/src/xine-engine/xine_internal.h
+++ b/src/xine-engine/xine_internal.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_internal.h,v 1.57 2001/11/20 14:03:15 miguelfreitas Exp $
+ * $Id: xine_internal.h,v 1.58 2001/11/28 22:19:12 miguelfreitas Exp $
*
*/
@@ -181,6 +181,8 @@ struct xine_s {
video_decoder_t *video_decoder_plugins[DECODER_PLUGIN_MAX];
video_decoder_t *cur_video_decoder_plugin;
int video_finished;
+
+ void *osd_renderer;
ao_instance_t *audio_out;
fifo_buffer_t *audio_fifo;