Re: OSD
Alban Bedel <[email protected]>
| Newsgroups | gmane.comp.video.mplayer.g2.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Alban Bedel, on Sat, 19 Jul 2003 15:12:32 +0200 you wrote: > > Hi, > > I worked a bit on OSD. Here is my current work. Comment are welcome :) Sorry for the chitty diff, i forgot to save the file after cleanup :( Albeu -- Everything is controlled by a small evil group to which, unfortunately, no one we know belongs. _______________________________________________ MPlayer-G2-dev mailing list [email protected] http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev
g2.osd.diff
(application/octet-stream, 24.6 KB)
--- /home/alban/MP/g2/Makefile Thu Jul 10 22:54:15 2003
+++ /home/alban/MP/g2.dev/Makefile Fri Jul 18 18:15:06 2003
@@ -10,7 +10,7 @@
STREAM_DEPS = demux/libmpdemux.a stream/libmpstream.a stream/mpdvdkit2/libmpdvdkit.a
CODECS_DEPS = audio/libmpacodecs.a video/libmpvcodecs.a libavcodec/libavcodec.a libavcodec/libpostproc/libpostproc.a \
audio/libaf/libaf.a video/libmpeg2/libmpeg2.a \
- audio/mp3lib/libMP3.a swscale/libswscale.a
+ audio/mp3lib/libMP3.a swscale/libswscale.a osd/libmposd.a
PLAYER_DEPS = libao2/libao2.a libvo2/libvo2.a
AO_LIBS = $(ARTS_LIB) $(ESD_LIB) $(NAS_LIB) $(SGIAUDIO_LIB) $(ALSA_LIB) $(SDL_LIB)
--- /home/alban/MP/g2/cfg.h Thu Jul 10 22:03:45 2003
+++ /home/alban/MP/g2.dev/cfg.h Fri Jul 18 17:35:57 2003
@@ -101,7 +101,9 @@
MODULE_TYPE_AF,
MODULE_TYPE_AD,
MODULE_TYPE_AE,
- MODULE_TYPE_AO
+ MODULE_TYPE_AO,
+
+ MODULE_TYPE_OSD
} module_type_t;
typedef struct config_data_s config_data_t;
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/osd/Makefile Fri Jul 18 18:24:12 2003
@@ -0,0 +1,46 @@
+
+BASE=..
+
+include $(BASE)/config.mak
+
+LIBNAME = libmposd.a
+
+SRCS=osd.c obj_test.c
+OBJS=$(SRCS:.c=.o)
+
+#CFLAGS = $(OPTFLAGS) -I. -Inative -I.. -I../libmpdemux -I../loader $(EXTRA_INC) -D_GNU_SOURCE
+CFLAGS = $(OPTFLAGS) -I. -I$(BASE) -I$(BASE)/video $(EXTRA_INC) -D_GNU_SOURCE
+
+.SUFFIXES: .c .o
+
+# .PHONY: all clean
+
+.c.o:
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+all: $(LIBNAME) $(LIBNAME2)
+
+$(LIBNAME): $(OBJS)
+ $(AR) sr $(LIBNAME) $(OBJS)
+
+$(LIBNAME2): $(OBJS2)
+ $(AR) sr $(LIBNAME2) $(OBJS2)
+
+clean:
+ rm -f *.o *.a *~
+
+distclean:
+ rm -f Makefile.bak $(OBJS) $(OBJS2) $(LIBNAME) $(LIBNAME2) *~ .depend
+
+dep: depend
+
+depend:
+ $(CC) -MM $(CFLAGS) $(SRCS) $(SRCS2) 1>.depend
+
+#
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
+
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/osd/obj_test.c Sat Jul 19 14:48:34 2003
@@ -0,0 +1,79 @@
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cfg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "osd.h"
+
+
+
+static int init(osd_obj_t*obj,void* param) {
+ printf("Obj init :)\n");
+ return 1;
+}
+
+static int config(osd_obj_t* obj,int width,int height,unsigned format){
+ switch(format) {
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ return 1;
+ default:
+ printf("Unsuported colorspace\n");
+ return 0;
+ }
+}
+
+static int draw(osd_obj_t* obj,mp_image_t* mpi){
+ int i,j;
+ char* dst;
+
+ if(!mpi) return 0;
+
+ dst = mpi->planes[0];
+ for(i = 0 ; i < mpi->height ; i++) {
+ for(j = 0 ; j < mpi->height ; j++) {
+ if(!((j+(i%2))% 4))
+ dst[j] = 255;
+ //else
+ //dst[j] = 255;
+ }
+ dst += mpi->stride[0];
+ }
+ obj->status = OSD_OBJ_SHOWN;
+ printf("\nObject drawn %d\n",obj->draw_id);
+ return 1;
+}
+
+static int control(osd_obj_t* obj,int request,void* data){
+ return 0;
+}
+
+static void uninit(osd_obj_t* obj){
+}
+
+
+static osd_obj_driver_t driver = {
+ init,
+ config,
+ draw,
+ control,
+ uninit
+};
+
+module_info_t osd_obj_test_driver = {
+ MODULE_TYPE_OSD,0,
+ &driver,
+ "test",
+ "Testing object",
+ "Albeu",
+ "Albeu",
+ "No comment",
+ 0,
+ NULL,
+ NULL,
+ 0
+};
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/osd/osd.c Sat Jul 19 14:50:34 2003
@@ -0,0 +1,371 @@
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cfg.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "osd.h"
+
+extern module_info_t osd_obj_test_driver;
+
+static module_info_t* obj_drivers[] = {
+ &osd_obj_test_driver,
+ NULL
+};
+
+module_info_t* find_osd_obj(char* name) {
+ int i;
+
+ for(i = 0 ; obj_drivers[i] ; i++) {
+ if(strcmp(obj_drivers[i]->name,name)) continue;
+ return obj_drivers[i];
+ }
+ return NULL;
+}
+
+
+static int osd_obj_in(osd_obj_t* o,int buf_type) {
+ osd_display_t* disp = o->display;
+ osd_area_t* a;
+
+ for(a = disp->areas ; a ; a = a->next) {
+ if(a->buffer_type != buf_type) {
+ // Fully contained in the wrong buffer type
+ if(o->x >= a->x && o->x+o->w <= a->x+a->w &&
+ o->y >= a->y && o->y+o->h <= a->y+a->h)
+ return 0;
+ // FIX ME
+ // Here we should in fact check the resting parts
+ // of the object but atm it doesn't matter.
+ continue;
+ }
+ // Doesn't cross the area
+ if(o->x+o->w < a->x || o->x >= a->x+a->w ||
+ o->y+o->h < a->y || o->y >= a->y+a->h)
+ continue;
+ // Match !!!
+ return 1;
+ }
+ return (disp && buf_type == disp->buffer_type);
+}
+
+static int get_obj_mpi(osd_obj_t* o,mp_image_t* mpi,mp_image_t* dmpi) {
+ int x1,y1,x2,y2;
+ if(!mpi) return 0;
+
+ // Cut the object if needed
+ x1 = o->x < 0 ? 0 : o->x;
+ y1 = o->y < 0 ? 0 : o->y;
+ x2 = o->x + o->w > mpi->width ? mpi->width : o->x + o->w;
+ y2 = o->y + o->h > mpi->height ? mpi->height : o->y + o->h;
+
+ // Legal size ?
+ if(x2 - x1 <= 0 || y2 - y1 <= 0) return 0;
+
+ // Setup the format stuff and the buffers
+ dmpi->x = o->x < 0 ? -o->x : 0;
+ dmpi->y = o->y < 0 ? -o->y : 0;
+ dmpi->width = x2 - x1;
+ dmpi->height = y2 - y1;
+
+ if(dmpi->imgfmt != mpi->imgfmt)
+ mp_image_setfmt(dmpi,mpi->imgfmt);
+
+ if(mpi->flags&MP_IMGFLAG_PLANAR) {
+ dmpi->planes[0] = mpi->planes[0] +
+ y1 * mpi->stride[0] + x1;
+ dmpi->planes[1] = mpi->planes[1] +
+ (y1>>mpi->chroma_y_shift) * mpi->stride[1] +
+ (x1>>mpi->chroma_x_shift);
+ dmpi->planes[2] = mpi->planes[2] +
+ (y1>>mpi->chroma_y_shift) * mpi->stride[2] +
+ (x1>>mpi->chroma_x_shift);
+ memcpy(dmpi->stride,mpi->stride,3*sizeof(int));
+ } else {
+ dmpi->planes[0] = mpi->planes[0] +
+ y1 * mpi->stride[0] + x1 * ((mpi->bpp+7)/8);
+ dmpi->stride[0] = mpi->stride[0];
+ }
+ return 1;
+}
+
+int osd_object_draw(osd_obj_t* o,mp_image_t* mpi) {
+ mp_image_t* i = NULL;
+ osd_obj_status_t *rec;
+ int r,drawing = (o->status == OSD_OBJ_DRAWING) ? 1 : 0;
+
+
+ if(o->status != OSD_OBJ_DRAWING &&
+ o->status != OSD_OBJ_SHOWN)
+ return 0;
+
+ // On locked area, kill it
+ if(osd_obj_in(o,OSD_BUF_LOCKED)) {
+ o->status = OSD_OBJ_HIDEN;
+ return 0;
+ }
+
+
+ // Try to find the buffer, in the records
+ for(rec = o->recs ; rec && rec->buffer != mpi->planes[0] ; rec = rec->next)
+ /* NOP */;
+ // Not found, allocate
+ if(!rec) {
+ rec = calloc(sizeof(osd_obj_status_t),1);
+ rec->buffer = mpi->planes[0];
+ rec->next = o->recs;
+ o->recs = rec;
+ printf("--- Allocate new object records for buffer %p\n",mpi->planes[0]);
+
+ }
+
+
+ // Get the mpi if we need to draw:
+ // We draw if the object is not drawn on the buffer,
+ // or the object must be updated, or we the object is over
+ // some TEMP area.
+ if( !rec->draw_id || o->draw_id != rec->draw_id ||
+ drawing || osd_obj_in(o,OSD_BUF_TEMP) ) {
+ if(!get_obj_mpi(o,mpi,&rec->mpi)) return -1;
+ i = &rec->mpi;
+ }
+
+
+ // Call the draw function. Call with NULL mpi mean that there
+ // is nothing to draw. This let the driver a chance to set itself to
+ // OSD_OBJ_DRAWING, so he can drawn something new at the next frame.
+ r = o->driver->draw(o,i);
+ if(r > 0) { // Success
+ if(i && drawing) // We draw something new
+ o->draw_id++; // Set the new draw id
+ // We record only objects wich are over STATIC
+ rec->draw_id = osd_obj_in(o,OSD_BUF_STATIC) ? o->draw_id : 0;
+ return (i != NULL) ? 1 : 0;
+ }
+ return r;
+}
+
+int osd_object_clear(osd_obj_t* o,mp_image_t* mpi) {
+ osd_obj_status_t *rec,*last = NULL;
+ int r = 0;
+
+ for(rec = o->recs ; rec && rec->buffer != mpi->planes[0] ; rec = rec->next)
+ last = rec;
+ // Never seen this buffer
+ if(!rec) return 0;
+ // Not drawn over this buffer
+ if(!rec->draw_id) return 0;
+ // Alredy drawn, don't need to update
+ if(o->status == OSD_OBJ_SHOWN && rec->draw_id == o->draw_id) return 0;
+
+ // Clear it
+ if(o->display->clear) r = o->display->clear(o->display,&rec->mpi);
+ // Some default clear would be nice
+ rec->draw_id = 0;
+
+ // Object must be deleted, remove this record
+ if(o->status == OSD_OBJ_DESTROY) {
+ if(last) last->next = rec->next;
+ else o->recs = rec->next;
+ free(rec);
+ }
+
+ return r;
+}
+
+int osd_display_draw(osd_display_t* disp, mp_image_t* mpi) {
+ osd_obj_t *o;
+ osd_obj_status_t *rec;
+ int ret = 0,r;
+
+
+ for(o = disp->objs ; o ; o = o->next ) {
+ r = osd_object_draw(o,mpi);
+ if(r < 0) {
+ printf("Error while drawing osd object\n");
+ continue;
+ }
+ ret += r;
+ }
+
+ return ret;
+}
+
+int osd_display_clear(osd_display_t* disp, mp_image_t* mpi) {
+ osd_obj_t *o,*last = NULL,*next;
+ osd_obj_status_t *rec;
+ int clr = 0,r;
+
+ for(o = disp->objs ; o ; o = next ) {
+ // Clear if needed
+ if(o->recs) {
+ r = osd_object_clear(o,mpi);
+ if(r < 0) printf("Clear failed\n");
+ else clr += r;
+ }
+ next = o->next;
+ if(o->status == OSD_OBJ_DESTROY && o->recs == NULL) {
+ if(last) last->next = o->next;
+ else disp->objs = o->next;
+ free(o);
+ } else
+ last = o;
+ }
+
+ return clr;
+}
+
+osd_display_t* osd_display_new(int width,int height,unsigned int format,
+ int buf_type) {
+ osd_display_t* disp = calloc(1,sizeof(osd_display_t));
+
+ disp->width = width;
+ disp->height = height;
+ disp->format = format;
+ disp->buffer_type = buf_type;
+
+ return disp;
+}
+
+osd_area_t* osd_display_add_area(osd_display_t* disp,int x,int y, int w, int h,
+ int buffer_type) {
+ osd_area_t* ret;
+
+ // TODO Check area size etc
+
+ ret = calloc(sizeof(osd_area_t),1);
+ ret->x = x;
+ ret->y = y;
+ ret->w = w;
+ ret->h = h;
+ ret->buffer_type = buffer_type;
+
+ ret->next = disp->areas;
+ disp->areas = ret;
+ return ret;
+}
+
+void osd_display_del_area(osd_display_t* disp,osd_area_t* area) {
+ osd_area_t *a,*l = NULL;
+
+ for(a = disp->areas ; a ; a = a->next) {
+ if(a != area) {
+ l = a;
+ continue;
+ }
+ if(l)
+ l->next = a->next;
+ else
+ disp->areas = NULL;
+ free(a);
+ return;
+ }
+ return;
+}
+
+osd_obj_t* osd_display_add_object(osd_display_t* disp,module_info_t* module,
+ void* cfg) {
+ osd_obj_t* obj;
+ obj = calloc(1,sizeof(osd_obj_t));
+ obj->driver = module->entry;
+ obj->display = disp;
+
+ if(!obj->driver->init(obj,cfg)) {
+ free(obj);
+ return NULL;
+ }
+
+ obj->next = disp->objs;
+ disp->objs = obj;
+
+ return obj;
+}
+
+
+int osd_object_set_size(osd_obj_t* obj,int width, int height) {
+
+ if(obj->status == OSD_OBJ_DESTROY) {
+ printf("Wrong object state: %d\n",obj->status);
+ return 0;
+ }
+
+ if(!obj->driver->config(obj,width,height,obj->display->format)) {
+ printf("Failed to set config %d x %d 0x%x\n",width,height,
+ obj->display->format);
+ return 0;
+ }
+
+ if(obj->status == OSD_OBJ_DISABLED)
+ obj->status = OSD_OBJ_HIDEN;
+
+ return 1;
+}
+
+int osd_object_show(osd_obj_t* obj,int show) {
+ if(obj->status == OSD_OBJ_DESTROY || obj->status == OSD_OBJ_DISABLED) {
+ printf("Wrong object state: %d\n",obj->status);
+ return 0;
+ }
+
+ if(show)
+ obj->status = OSD_OBJ_DRAWING;
+ else
+ obj->status = OSD_OBJ_HIDEN;
+
+ return 1;
+}
+
+
+void osd_display_del_object(osd_display_t* disp,osd_obj_t* obj) {
+ osd_obj_t *o;
+
+ for(o = disp->objs ; o ; o = o->next ) {
+ if(o != obj) continue;
+ if(o->driver && o->driver->uninit)
+ o->driver->uninit(o);
+ // Set the destroy state
+ o->status = OSD_OBJ_DESTROY;
+ return;
+ }
+ return;
+}
+
+int osd_display_config(osd_display_t* disp,int width,int height,unsigned format) {
+ osd_obj_t *o;
+ int fail = 0;
+
+ disp->width = width;
+ disp->height = height;
+ disp->format = format;
+
+ for(o = disp->objs ; o ; o = o->next ) {
+ if(o->status == OSD_OBJ_DESTROY) continue;
+ if(!o->driver->config(o,o->w,o->h,format)) {
+ o->status = OSD_OBJ_DISABLED;
+ fail++;
+ continue;
+ }
+ if(o->status == OSD_OBJ_DISABLED)
+ o->status = OSD_OBJ_HIDEN;
+ }
+ return fail;
+}
+
+int osd_display_show_all(osd_display_t* disp) {
+ osd_obj_t *o;
+ int fail = 0;
+
+ for(o = disp->objs ; o ; o = o->next ) {
+ if(!osd_object_show(o,1))
+ fail++;
+ }
+ return fail;
+}
+
+void osd_display_free(osd_display_t* disp) {
+ // TODO
+
+}
+
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/osd/osd.h Sat Jul 19 12:35:30 2003
@@ -0,0 +1,120 @@
+
+// TEMP:
+// osd need to be redraw all the time
+
+// STATIC:
+// osd don't need to be redraw at every frames
+// original data must be saved to clear the buffer (or call a provided
+// clear func)
+
+// IP(B):
+// we can't draw osd on that.
+#define OSD_BUF_TEMP 0
+#define OSD_BUF_STATIC 1
+#define OSD_BUF_LOCKED 2
+
+// Area flags
+#define OSD_AREA_UPDATED 1
+
+// Object status
+#define OSD_OBJ_DISABLED 0
+#define OSD_OBJ_HIDEN 1
+#define OSD_OBJ_DRAWING 2
+#define OSD_OBJ_SHOWN 3
+#define OSD_OBJ_DESTROY 4
+
+typedef struct osd_area_st osd_area_t;
+struct osd_area_st {
+ int x,y;
+ int w,h;
+ int buffer_type; // TEMP, STATIC, LOCKED
+ int flags; // dirty flags for static
+ osd_area_t* next;
+};
+
+typedef struct osd_obj_st osd_obj_t;
+typedef struct osd_display_st osd_display_t;
+
+typedef struct osd_obj_driver_st {
+ int (*init)(osd_obj_t*,void* param);
+ int (*config)(osd_obj_t*,int width,int height,unsigned format);
+ int (*draw)(osd_obj_t*,mp_image_t*);
+ int (*control)(osd_obj_t*,int,void*);
+ void (*uninit)(osd_obj_t*);
+} osd_obj_driver_t;
+
+
+typedef struct osd_obj_status_st osd_obj_status_t;
+
+struct osd_obj_st {
+ int x,y;
+ int w,h;
+ int status;
+ int flags;
+ unsigned int draw_id; // auto inc at each (real) draw
+ mp_image_t mpi; // Mpi we give to this object for draw
+ osd_display_t* display;
+ osd_obj_t* next;
+ osd_obj_driver_t* driver;
+ osd_obj_status_t* recs; // Per buffer records
+};
+
+typedef int (*osd_clear_func_t)(osd_display_t* disp, mp_image_t* mpi);
+
+struct osd_obj_status_st {
+ void* buffer; // Pointer to the buffer start (as id)
+ unsigned int draw_id; // Draw id
+ mp_image_t mpi;
+ osd_obj_status_t* next;
+};
+
+typedef struct osd_buffer_st osd_buffer_t;
+struct osd_buffer_st {
+ void* buffer;
+ int age;
+ osd_obj_status_t* objs;
+ osd_buffer_t* next;
+};
+
+
+struct osd_display_st {
+ int width,height;
+ float aspect_ratio;
+ unsigned int format;
+ int buffer_type; // TEMP, STATIC
+ int flags; // dirty flags for static
+ osd_area_t* areas; // desc of various sub area properties
+ // clear callback
+ osd_clear_func_t clear;
+ osd_buffer_t* bufs; // buffers record for clearing
+
+ // objs attached to the display
+ osd_obj_t* objs;
+};
+
+
+osd_display_t* osd_display_new(int width,int height,unsigned int format,
+ int buf_type);
+
+osd_area_t* osd_display_add_area(osd_display_t* disp,int x,int y, int w, int h,
+ int buffer_type);
+void osd_display_del_area(osd_display_t* disp,osd_area_t* area);
+
+osd_obj_t* osd_display_add_object(osd_display_t* disp,module_info_t* module,
+ void* cfg);
+
+int osd_display_config(osd_display_t* disp,int width,int height,unsigned format);
+
+int osd_object_set_size(osd_obj_t* obj,int width, int height);
+int osd_object_show(osd_obj_t* obj,int show);
+
+int osd_display_show_all(osd_display_t* disp);
+void osd_display_del_object(osd_display_t* disp,osd_obj_t* obj);
+
+
+int osd_display_draw(osd_display_t* disp, mp_image_t* mpi);
+int osd_display_clear(osd_display_t* disp, mp_image_t* mpi);
+
+void osd_display_free(osd_display_t* disp);
+
+module_info_t* find_osd_obj(char* name);
--- /home/alban/MP/g2/video/Makefile Mon May 12 01:47:03 2003
+++ /home/alban/MP/g2.dev/video/Makefile Fri Jul 18 18:13:06 2003
@@ -12,7 +12,7 @@
VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT)
# vf_vo.c
-VFILTER_SRCS=vf.c vf_scale.c vf_vo2.c vf_vd.c vf_pp.c vf_format.c vf_tfields.c # vf_crop.c vf_expand.c # vf_format.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_rectangle.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c
+VFILTER_SRCS=vf.c vf_scale.c vf_vo2.c vf_vd.c vf_pp.c vf_format.c vf_tfields.c vf_osd.c # vf_crop.c vf_expand.c # vf_format.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_rectangle.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c
ENCODER_SRCS=ve.c # ve_lavc.c # ve_divx4.c ve_vfw.c ve_rawrgb.c ve_libdv.c ve_xvid.c ve_qtvideo.c ve_nuv.c
# NATIVE_SRCS=native/RTjpegN.c native/cinepak.c native/fli.c native/minilzo.c native/msvidc.c native/nuppelvideo.c native/qtrle.c native/qtrpza.c native/qtsmc.c native/roqav.c native/xa_gsm.c native/svq1.c
--- /home/alban/MP/g2/video/vf.c Sun Jul 13 23:52:25 2003
+++ /home/alban/MP/g2.dev/video/vf.c Fri Jul 18 18:12:46 2003
@@ -60,11 +60,13 @@
extern vf_info_t vf_info_detc;
extern vf_info_t vf_info_telecine;
extern vf_info_t vf_info_tfields;
+extern vf_info_t vf_info_osd;
//char** vo_plugin_args=(char**) NULL;
// list of available filters:
static vf_info_t* filter_list[]={
+ &vf_info_osd,
&vf_info_scale,
&vf_info_vo2,
&vf_info_vd,
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/video/vf_osd.c Sat Jul 19 14:51:03 2003
@@ -0,0 +1,245 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "config.h"
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "fastmemcpy.h"
+
+#include "cfg.h"
+#include "osd/osd.h"
+
+
+static struct config_data_s {
+ int w,h;
+ int x,y;
+ int force_osd;
+ config_modlist_t* objs;
+} cfg_def = {
+ 0,0,
+ -1,-1,
+ 0,
+ NULL
+};
+
+static config_t cfg_opts[] = {
+ {"w",&cfg_def.w, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL, "Expand to width"},
+ {"h",&cfg_def.h, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL, "Expand to height"},
+ {"x",&cfg_def.x, CONF_TYPE_INT, CONF_MIN, -1, 0, NULL, "Expand offset"},
+ {"y",&cfg_def.y, CONF_TYPE_INT, CONF_MIN, -1, 0, NULL, "Expand offset"},
+ {"force",&cfg_def.force_osd, CONF_TYPE_FLAG,0, 0, 1, NULL, "Alway draw osd everywhere"},
+ {"objs",&cfg_def.objs, CONF_TYPE_MODLIST, 0, 0, 0, find_osd_obj, "object"},
+ {NULL, NULL, 0, 0, 0, 0, NULL, NULL}
+};
+
+
+struct vf_priv_s {
+ osd_display_t* disp;
+ osd_area_t* m_area;
+ int exp_x,exp_y,exp_w,exp_h;
+ int x,y,w,h;
+ int force_osd;
+ int n;
+};
+
+static int osd_clear_func(osd_display_t* disp, mp_image_t* mpi) {
+ printf("------- Clear ------\n");
+ vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
+ return 1;
+}
+
+int config(struct vf_instance_s* vf,
+ int width, int height, int d_width, int d_height,
+ unsigned int flags, unsigned int outfmt) {
+ vf->priv->exp_w = vf->priv->w > width ? vf->priv->w : width;
+ vf->priv->exp_h = vf->priv->h > height ? vf->priv->h : height;
+
+ vf->priv->exp_x = vf->priv->x >= 0 ? vf->priv->x : (vf->priv->exp_w - width)/2;
+ vf->priv->exp_y = vf->priv->y >= 0 ? vf->priv->y : (vf->priv->exp_h - height)/2;
+
+ if(vf->priv->exp_x + width > vf->priv->exp_w ||
+ vf->priv->exp_y + height > vf->priv->exp_h)
+ return 0;
+
+ if(vf->priv->exp_w > width || vf->priv->exp_h > height) {
+ if(!vf->priv->m_area) {
+ vf->priv->m_area = osd_display_add_area(vf->priv->disp,
+ vf->priv->exp_x,
+ vf->priv->exp_y,
+ width,height,
+ OSD_BUF_TEMP);
+ vf->priv->disp->buffer_type = OSD_BUF_STATIC;
+ } else {
+ vf->priv->m_area->x = vf->priv->exp_x;
+ vf->priv->m_area->y = vf->priv->exp_y;
+ vf->priv->m_area->w = width;
+ vf->priv->m_area->h = height;
+ }
+ } else {
+ if(vf->priv->m_area) {
+ osd_display_del_area(vf->priv->disp,vf->priv->m_area);
+ vf->priv->m_area = NULL;
+ vf->priv->disp->buffer_type = OSD_BUF_TEMP;
+ }
+ }
+ osd_display_config(vf->priv->disp,vf->priv->exp_w,vf->priv->exp_h,outfmt);
+ //osd_display_show_all(vf->priv->disp);
+ return vf_next_config(vf,vf->priv->exp_w,vf->priv->exp_h,vf->priv->exp_w,vf->priv->exp_h,flags,outfmt);
+}
+
+void get_image(struct vf_instance_s* vf,
+ mp_image_t *mpi) {
+ mp_image_t *dmpi = NULL;
+
+ if(vf->priv->exp_w==mpi->width ||
+ (mpi->flags&(MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ACCEPT_WIDTH)) ){
+ // try full DR !
+ if(vf->priv->force_osd && mpi->type != MP_IMGTYPE_TEMP)
+ return;
+ mpi->priv=dmpi=vf_get_image_cloned(vf->next,mpi,mpi->imgfmt,
+ mpi->type, mpi->flags,
+ vf->priv->exp_w,vf->priv->exp_h);
+ // set up mpi as a cropped-down image of dmpi:
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ mpi->planes[0]=dmpi->planes[0]+
+ vf->priv->exp_y*dmpi->stride[0]+vf->priv->exp_x;
+ mpi->planes[1]=dmpi->planes[1]+
+ (vf->priv->exp_y>>mpi->chroma_y_shift)*dmpi->stride[1]+(vf->priv->exp_x>>mpi->chroma_x_shift);
+ mpi->planes[2]=dmpi->planes[2]+
+ (vf->priv->exp_y>>mpi->chroma_y_shift)*dmpi->stride[2]+(vf->priv->exp_x>>mpi->chroma_x_shift);
+ mpi->stride[1]=dmpi->stride[1];
+ mpi->stride[2]=dmpi->stride[2];
+ } else {
+ mpi->planes[0]=dmpi->planes[0]+
+ vf->priv->exp_y*dmpi->stride[0]+
+ vf->priv->exp_x*(dmpi->bpp/8);
+ }
+ mpi->stride[0]=dmpi->stride[0];
+ mpi->width=dmpi->width;
+ mpi->flags|=MP_IMGFLAG_DIRECT;
+ if(mpi->type != MP_IMGTYPE_TEMP) {
+ if(vf->priv->m_area)
+ vf->priv->m_area->buffer_type = OSD_BUF_LOCKED;
+ else
+ vf->priv->disp->buffer_type = OSD_BUF_LOCKED;
+ } else {
+ if(vf->priv->m_area)
+ vf->priv->m_area->buffer_type = OSD_BUF_TEMP;
+ else
+ vf->priv->disp->buffer_type = OSD_BUF_TEMP;
+ }
+ osd_display_clear(vf->priv->disp,dmpi);
+ }
+}
+
+
+inline static void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi, int x, int y) {
+ if(mpi->flags&MP_IMGFLAG_PLANAR){
+ memcpy_pic(dmpi->planes[0] + y*dmpi->stride[0] + x,
+ mpi->planes[0], mpi->width, mpi->height,
+ dmpi->stride[0],mpi->stride[0]);
+ memcpy_pic(dmpi->planes[1] + y*dmpi->stride[1] + x/2,
+ mpi->planes[1], mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[1],mpi->stride[1]);
+ memcpy_pic(dmpi->planes[2] + y*dmpi->stride[2] + x/2,
+ mpi->planes[2], mpi->chroma_width, mpi->chroma_height,
+ dmpi->stride[2],mpi->stride[2]);
+ } else {
+ memcpy_pic(dmpi->planes[0] + y*dmpi->stride[0] + x*(dmpi->bpp/8),
+ mpi->planes[0],
+ mpi->width*(mpi->bpp/8), mpi->height,
+ dmpi->stride[0],mpi->stride[0]);
+ }
+}
+
+mp_image_t* process_image(struct vf_instance_s* vf, mp_image_t* mpi,int drop) {
+ mp_image_t* dmpi = mpi->priv;
+
+
+ if(!(mpi->flags&MP_IMGFLAG_DIRECT) || !dmpi) {
+ dmpi = vf_get_image_cloned(vf->next,mpi,mpi->imgfmt,
+ MP_IMGTYPE_TEMP, 0,
+ vf->priv->exp_w, vf->priv->exp_h);
+ if(!dmpi) return NULL;
+ osd_display_clear(vf->priv->disp,dmpi);
+ copy_mpi(dmpi,mpi,vf->priv->exp_x,vf->priv->exp_y);
+ } else
+ vf_clone_mpi(dmpi,mpi);
+
+ osd_display_draw(vf->priv->disp,dmpi);
+
+
+ if(vf->priv->disp->objs && vf->priv->n % 25 == 0) {
+ if(vf->priv->n % 50 == 0) {
+ printf("---- SHOW ---- \n");
+ osd_object_show(vf->priv->disp->objs,1);
+ } else {
+ printf("===== HIDE =====\n");
+ osd_object_show(vf->priv->disp->objs,0);
+ }
+ }
+ vf->priv->n++;
+
+ return dmpi;
+}
+
+static int open(vf_instance_t *vf, void* cfg){
+ config_data_t* opts = vf->cfg ? vf->cfg : &cfg_def;
+
+ vf->config=config;
+ vf->get_image=get_image;
+ vf->process_image=process_image;
+ vf->priv=calloc(1,sizeof(struct vf_priv_s));
+
+
+
+
+ vf->priv->disp = calloc(sizeof(osd_display_t),1);
+ vf->priv->disp->clear = osd_clear_func;
+ vf->priv->disp->buffer_type = OSD_BUF_TEMP;
+
+ vf->priv->x = opts->x;
+ vf->priv->y = opts->y;
+ vf->priv->w = opts->w;
+ vf->priv->h = opts->h;
+ vf->priv->force_osd = opts->force_osd;
+
+ if(opts->objs) {
+ int i;
+ printf("\n\n ADDIDNG OSD OBJ \n\n");
+ for(i = 0 ; opts->objs[i].mod ; i++) {
+ osd_obj_t* o = osd_display_add_object(vf->priv->disp, opts->objs[i].mod,
+ opts->objs[i].cfg);
+ if(!o)
+ printf("Failed to add object %s\n",opts->objs[i].mod->name);
+ else {
+ printf("Added osd object %s\n",opts->objs[i].mod->name);
+ o->w = o->h = 60;
+ o->x = o->y = 80;
+ }
+ }
+ }
+
+
+
+ return 1;
+}
+
+
+vf_info_t vf_info_osd = {
+ MODULE_TYPE_VF, MODULE_VERSION,
+ open,
+ "osd",
+ "on screen display",
+ "Albeu",
+ "Albeu",
+ "",
+ 0,
+ cfg_opts, &cfg_def, sizeof(struct config_data_s)
+};