Commit 26e60046 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Forward port of branches/0.8.1-jpsaman-thedj revision 12070. The OSD menu...

Forward port of branches/0.8.1-jpsaman-thedj revision 12070. The OSD menu subsystem consists of two parts a core part (src/osd, include/vlc_osd.h) and a subfilter (modules/video_filter/osdmenu.c). The OSD menu can be used locally or it can be streamed. It depends on the way the functionality is called from the vlc commandline. Currently there is only one way to make the subpictures appear on the video and that is through the rc-interface. The following commands are supported by it: "menu on" (show OSD menu), "menu off" (hide OSD menu), "menu left" (highlight button on the left), "menu right" (highlight button on the right), "menu up" (highlight button above), "menu down" (highlight button below) or "menu select" (perform hotkey action). When there is no button on the left, right, up or down then the menu-command will be ignored.

To stream use a commandline similar to this:

./vlc dvdsimple:///dev/dvd --sub-filter=osdmenu --osdmenu-file=share/osdmenu/default.cfg --extraintf rc --sout '#transcode{sfilter=osdmenu}:std{mux=ts,access=udp,url=127.0.0.1:1234}' -vvvv

For local playback a commandline like this is needed:

./vlc dvdsimple:///dev/dvd --sub-filter=osdmenu --osdmenu-file=share/osdmenu/default.cfg -vvvv

Have fun with the basic functionality - jpsaman.
parent d8fc9f3b
......@@ -112,6 +112,7 @@ HEADERS_include = \
include/vlc_messages.h \
include/vlc_meta.h \
include/vlc_objects.h \
include/vlc_osd.h \
include/vlc_playlist.h \
include/vlc_spu.h \
include/vlc_stream.h \
......@@ -382,6 +383,9 @@ SOURCES_libvlc_common = \
src/stream_output/announce.c \
src/stream_output/sap.c \
src/stream_output/acl.c \
src/osd/osd.c \
src/osd/osd_widgets.c \
src/osd/osd_parser.c \
src/misc/charset.c \
src/misc/httpd.c \
src/misc/tls.c \
......@@ -813,6 +817,49 @@ package-win32-base:
cp $$i $(top_builddir)/vlc-${VERSION}/skins/ || true ; \
done
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/dvd"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/dvd/selected"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/dvd/unselect"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/dvd/selection"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/dvd/volume"
for i in $(srcdir)/share/osdmenu/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/ || true ; \
unix2dos $(srcdir)/vlc-${VERSION}/osdmenu/`basename $$i` ; \
done
for i in $(srcdir)/share/osdmenu/dvd/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/dvd || true ; \
done
for i in $(srcdir)/share/osdmenu/dvd/unselect/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/dvd/unselect || true ; \
done
for i in $(srcdir)/share/osdmenu/dvd/selected/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/dvd/selected/ || true ; \
done
for i in $(srcdir)/share/osdmenu/dvd/selection/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/dvd/selection/ || true ; \
done
for i in $(srcdir)/share/osdmenu/dvd/volume/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/dvd/volume/ || true ; \
done
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/default"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/default/selected"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/default/selection"
mkdir -p "$(srcdir)/vlc-${VERSION}/osdmenu/default/volume"
for i in $(srcdir)/share/osdmenu/default/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/default || true ; \
done
for i in $(srcdir)/share/osdmenu/default/selected/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/default/selected/ || true ; \
done
for i in $(srcdir)/share/osdmenu/default/selection/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/default/selection/ || true ; \
done
for i in $(srcdir)/share/osdmenu/default/volume/*.*; do \
cp $$i $(srcdir)/vlc-${VERSION}/osdmenu/default/volume/ || true ; \
done
mkdir -p "$(top_builddir)/vlc-${VERSION}/http/admin"
mkdir -p "$(top_builddir)/vlc-${VERSION}/http/vlm"
cp $(srcdir)/share/http/*.html $(top_builddir)/vlc-${VERSION}/http/ ;
......
......@@ -2689,6 +2689,7 @@ AC_CHECK_HEADERS(png.h, [
AC_CHECK_LIB(png, png_set_rows, [
VLC_ADD_LDFLAGS([png],[-lpng -lz])
VLC_ADD_PLUGINS([png])
VLC_ADD_PLUGINS([osdmenu])
AC_DEFINE(HAVE_LIBPNG, [], [Define if you have the PNG library: libpng])],
[],[-lz])
LDFLAGS="${LDFLAGS_save}"
......
/*****************************************************************************
* stream_output.h : stream output module
*****************************************************************************
* Copyright (C) 2002 the VideoLAN team
* Copyright (C) 2002-2005 the VideoLAN team
* $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
* Jean-Paul Saman <jpsaman #_at_# m2x.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -206,6 +207,9 @@ struct sout_stream_t
sout_cfg_t *p_cfg;
char *psz_next;
/* Subpicture unit */
spu_t *p_spu;
/* add, remove a stream */
sout_stream_id_t *(*pf_add)( sout_stream_t *, es_format_t * );
int (*pf_del)( sout_stream_t *, sout_stream_id_t * );
......
......@@ -405,6 +405,13 @@ typedef struct vod_media_t vod_media_t;
typedef struct opengl_t opengl_t;
typedef struct opengl_sys_t opengl_sys_t;
/* osdmenu */
typedef struct osd_menu_t osd_menu_t;
typedef struct osd_state_t osd_state_t;
typedef struct osd_event_t osd_event_t;
typedef struct osd_button_t osd_button_t;
typedef struct osd_menu_state_t osd_menu_state_t;
/* VLM */
typedef struct vlm_t vlm_t;
typedef struct vlm_message_t vlm_message_t;
......
......@@ -59,6 +59,7 @@
#define VLC_OBJECT_TLS (-25)
#define VLC_OBJECT_SD (-26)
#define VLC_OBJECT_XML (-27)
#define VLC_OBJECT_OSDMENU (-28)
#define VLC_OBJECT_GENERIC (-666)
......
This diff is collapsed.
......@@ -391,6 +391,22 @@ struct module_symbols_t
char * (*__vlc_fix_readdir_charset_inner) (vlc_object_t *, const char *);
int (*vlc_scandir_inner) (const char *name, struct dirent ***namelist, int (*filter) ( const struct dirent * ), int (*compar) ( const struct dirent **, const struct dirent ** ));
int (*vlc_alphasort_inner) (const struct dirent **a, const struct dirent **b);
osd_state_t * (*__osd_StateChange_inner) (osd_state_t *, const int);
picture_t * (*osd_Slider_inner) (int i_width, int i_height, int i_position, short i_type);
void (*osd_ConfigUnload_inner) (vlc_object_t *, osd_menu_t **);
void (*__osd_MenuShow_inner) (vlc_object_t *);
picture_t * (*osd_Icon_inner) (int i_width, int i_height, short i_type);
void (*__osd_VolumeDown_inner) (vlc_object_t *);
void (*__osd_MenuNext_inner) (vlc_object_t *);
void (*__osd_MenuDelete_inner) (vlc_object_t *, osd_menu_t *);
void (*__osd_MenuHide_inner) (vlc_object_t *);
int (*osd_ConfigLoader_inner) (vlc_object_t *, const char *, osd_menu_t **);
void (*__osd_MenuUp_inner) (vlc_object_t *);
void (*__osd_MenuDown_inner) (vlc_object_t *);
osd_menu_t * (*__osd_MenuCreate_inner) (vlc_object_t *, const char *);
void (*__osd_MenuPrev_inner) (vlc_object_t *);
void (*__osd_VolumeUp_inner) (vlc_object_t *);
void (*__osd_MenuActivate_inner) (vlc_object_t *);
};
# if defined (__PLUGIN__)
# define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
......@@ -766,6 +782,22 @@ struct module_symbols_t
# define __vlc_fix_readdir_charset (p_symbols)->__vlc_fix_readdir_charset_inner
# define vlc_scandir (p_symbols)->vlc_scandir_inner
# define vlc_alphasort (p_symbols)->vlc_alphasort_inner
# define __osd_StateChange (p_symbols)->__osd_StateChange_inner
# define osd_Slider (p_symbols)->osd_Slider_inner
# define osd_ConfigUnload (p_symbols)->osd_ConfigUnload_inner
# define __osd_MenuShow (p_symbols)->__osd_MenuShow_inner
# define osd_Icon (p_symbols)->osd_Icon_inner
# define __osd_VolumeDown (p_symbols)->__osd_VolumeDown_inner
# define __osd_MenuNext (p_symbols)->__osd_MenuNext_inner
# define __osd_MenuDelete (p_symbols)->__osd_MenuDelete_inner
# define __osd_MenuHide (p_symbols)->__osd_MenuHide_inner
# define osd_ConfigLoader (p_symbols)->osd_ConfigLoader_inner
# define __osd_MenuUp (p_symbols)->__osd_MenuUp_inner
# define __osd_MenuDown (p_symbols)->__osd_MenuDown_inner
# define __osd_MenuCreate (p_symbols)->__osd_MenuCreate_inner
# define __osd_MenuPrev (p_symbols)->__osd_MenuPrev_inner
# define __osd_VolumeUp (p_symbols)->__osd_VolumeUp_inner
# define __osd_MenuActivate (p_symbols)->__osd_MenuActivate_inner
# elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
/******************************************************************
* STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
......@@ -1144,6 +1176,22 @@ struct module_symbols_t
((p_symbols)->__vlc_fix_readdir_charset_inner) = __vlc_fix_readdir_charset; \
((p_symbols)->vlc_scandir_inner) = vlc_scandir; \
((p_symbols)->vlc_alphasort_inner) = vlc_alphasort; \
((p_symbols)->__osd_StateChange_inner) = __osd_StateChange; \
((p_symbols)->osd_Slider_inner) = osd_Slider; \
((p_symbols)->osd_ConfigUnload_inner) = osd_ConfigUnload; \
((p_symbols)->__osd_MenuShow_inner) = __osd_MenuShow; \
((p_symbols)->osd_Icon_inner) = osd_Icon; \
((p_symbols)->__osd_VolumeDown_inner) = __osd_VolumeDown; \
((p_symbols)->__osd_MenuNext_inner) = __osd_MenuNext; \
((p_symbols)->__osd_MenuDelete_inner) = __osd_MenuDelete; \
((p_symbols)->__osd_MenuHide_inner) = __osd_MenuHide; \
((p_symbols)->osd_ConfigLoader_inner) = osd_ConfigLoader; \
((p_symbols)->__osd_MenuUp_inner) = __osd_MenuUp; \
((p_symbols)->__osd_MenuDown_inner) = __osd_MenuDown; \
((p_symbols)->__osd_MenuCreate_inner) = __osd_MenuCreate; \
((p_symbols)->__osd_MenuPrev_inner) = __osd_MenuPrev; \
((p_symbols)->__osd_VolumeUp_inner) = __osd_VolumeUp; \
((p_symbols)->__osd_MenuActivate_inner) = __osd_MenuActivate; \
(p_symbols)->net_ConvertIPv4_deprecated = NULL; \
(p_symbols)->vlc_fix_readdir_charset_deprecated = NULL; \
......
......@@ -342,6 +342,8 @@ $Id$
* opie: interface for Opie using QT/Embedded library.
* osdmenu: video_filter for displaying and streaming a On Screen Display menu
* oss: audio output module using the OSS /dev/dsp interface.
* packetizer_copy: Simple copy packetizer
......
......@@ -1557,16 +1557,247 @@ static int OpenEncoder( vlc_object_t *p_this )
return VLC_SUCCESS;
}
/* FIXME: this routine is a hack to convert VLC_FOURCC('Y','U','V','A')
* into VLC_FOURCC('Y','U','V','P')
*/
static subpicture_t *YuvaYuvp( encoder_t *p_enc, subpicture_t *p_subpic )
{
subpicture_region_t *p_region = NULL;
for( p_region = p_subpic->p_region; p_region; p_region = p_region->p_next )
{
video_format_t *p_fmt = &p_region->fmt;
int i = 0, j = 0, n = 0, p = 0;
int i_max_entries = 256;
#ifdef RANDOM_DITHERING
int i_seed = 0xdeadbeef; /* random seed */
#else
int *pi_delta;
#endif
int i_pixels = p_region->picture.p[0].i_visible_lines
* p_region->picture.p[0].i_pitch;
int i_iterator = p_region->picture.p[0].i_visible_lines * 3 / 4
* p_region->picture.p[0].i_pitch
+ p_region->picture.p[0].i_pitch * 1 / 3;
int i_tolerance = 0;
p_fmt->i_chroma = VLC_FOURCC('Y','U','V','P');
p_fmt->p_palette = (video_palette_t *) malloc( sizeof( video_palette_t ) );
p_fmt->p_palette->i_entries = 0;
/* Find best iterator using Euclide’s algorithm */
for( ; i_iterator > 1 ; i_iterator-- )
{
int a = i_pixels;
int b = i_iterator;
int c;
while( b )
{
c = a % b;
a = b;
b = c;
}
if( a == 1 )
{
break;
}
}
/* Count colors, build best palette */
for( i_tolerance = 0; i_tolerance < 128; i_tolerance++ )
{
vlc_bool_t b_success = VLC_TRUE;
p_fmt->p_palette->i_entries = 0;
for( i = 0; i < i_pixels ; )
{
uint8_t y, u, v, a;
y = p_region->picture.p[0].p_pixels[i];
u = p_region->picture.p[1].p_pixels[i];
v = p_region->picture.p[2].p_pixels[i];
a = p_region->picture.p[3].p_pixels[i];
for( j = 0; j < p_fmt->p_palette->i_entries; j++ )
{
if( abs((int)p_fmt->p_palette->palette[j][0] - (int)y) <= i_tolerance &&
abs((int)p_fmt->p_palette->palette[j][1] - (int)u) <= i_tolerance &&
abs((int)p_fmt->p_palette->palette[j][2] - (int)v) <= i_tolerance &&
abs((int)p_fmt->p_palette->palette[j][3] - (int)a) <= i_tolerance / 2 )
{
break;
}
}
if( j == p_fmt->p_palette->i_entries )
{
p_fmt->p_palette->palette[j][0] = y;
p_fmt->p_palette->palette[j][1] = u;
p_fmt->p_palette->palette[j][2] = v;
p_fmt->p_palette->palette[j][3] = a;
p_fmt->p_palette->i_entries++;
}
if( p_fmt->p_palette->i_entries >= i_max_entries )
{
b_success = VLC_FALSE;
break;
}
i += i_iterator;
if( i > i_pixels )
{
i -= i_pixels;
}
}
if( b_success )
{
break;
}
}
#if DEBUG_DVBSUB
msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
#endif
#ifndef RANDOM_DITHERING
pi_delta = malloc( ( p_region->picture.p[0].i_pitch + 1 )
* sizeof(int) * 4 );
for( i = 0; i < (p_region->picture.p[0].i_pitch + 1) * 4 ; i++ )
{
pi_delta[ i ] = 0;
}
#endif
/* Fill image with our new colours */
for( p = 0; p < p_region->picture.p[0].i_visible_lines ; p++ )
{
int i_ydelta = 0, i_udelta = 0, i_vdelta = 0, i_adelta = 0;
for( n = 0; n < p_region->picture.p[0].i_pitch ; n++ )
{
int i_offset = p * p_region->picture.p[0].i_pitch + n;
int y, u, v, a;
int i_mindist, i_best;
y = (int)p_region->picture.p[0].p_pixels[i_offset];
u = (int)p_region->picture.p[1].p_pixels[i_offset];
v = (int)p_region->picture.p[2].p_pixels[i_offset];
a = (int)p_region->picture.p[3].p_pixels[i_offset];
/* Add dithering compensation */
#ifdef RANDOM_DITHERING
y += ((i_seed & 0xff) - 0x80) * i_tolerance / 0x80;
u += (((i_seed >> 8) & 0xff) - 0x80) * i_tolerance / 0x80;
v += (((i_seed >> 16) & 0xff) - 0x80) * i_tolerance / 0x80;
a += (((i_seed >> 24) & 0xff) - 0x80) * i_tolerance / 0x80;
#else
y += i_ydelta + pi_delta[ n * 4 ];
u += i_udelta + pi_delta[ n * 4 + 1 ];
v += i_vdelta + pi_delta[ n * 4 + 2 ];
a += i_adelta + pi_delta[ n * 4 + 3 ];
#endif
/* Find best colour in palette */
for( i_mindist = 99999999, i_best = 0, j = 0; j < p_fmt->p_palette->i_entries; j++ )
{
int i_dist = 0;
i_dist += abs((int)p_fmt->p_palette->palette[j][0] - y);
i_dist += abs((int)p_fmt->p_palette->palette[j][1] - u);
i_dist += abs((int)p_fmt->p_palette->palette[j][2] - v);
i_dist += 2 * abs((int)p_fmt->p_palette->palette[j][3] - a);
if( i_dist < i_mindist )
{
i_mindist = i_dist;
i_best = j;
}
}
/* Set pixel to best color */
p_region->picture.p[0].p_pixels[i_offset] = i_best;
/* Update dithering state */
#ifdef RANDOM_DITHERING
i_seed = (i_seed * 0x1283837) ^ 0x789479 ^ (i_seed >> 13);
#else
i_ydelta = y - (int)p_fmt->p_palette->palette[i_best][0];
i_udelta = u - (int)p_fmt->p_palette->palette[i_best][1];
i_vdelta = v - (int)p_fmt->p_palette->palette[i_best][2];
i_adelta = a - (int)p_fmt->p_palette->palette[i_best][3];
pi_delta[ n * 4 ] = i_ydelta * 3 / 8;
pi_delta[ n * 4 + 1 ] = i_udelta * 3 / 8;
pi_delta[ n * 4 + 2 ] = i_vdelta * 3 / 8;
pi_delta[ n * 4 + 3 ] = i_adelta * 3 / 8;
i_ydelta = i_ydelta * 5 / 8;
i_udelta = i_udelta * 5 / 8;
i_vdelta = i_vdelta * 5 / 8;
i_adelta = i_adelta * 5 / 8;
#endif
}
}
#ifndef RANDOM_DITHERING
free( pi_delta );
#endif
/* pad palette */
for( i = p_fmt->p_palette->i_entries; i < i_max_entries; i++ )
{
p_fmt->p_palette->palette[i][0] = 0;
p_fmt->p_palette->palette[i][1] = 0;
p_fmt->p_palette->palette[i][2] = 0;
p_fmt->p_palette->palette[i][3] = 0;
}
p_fmt->p_palette->i_entries = i_max_entries;
#if DEBUG_DVBSUB
msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
#endif
}
return p_subpic;
} /* End of hack */
/****************************************************************************
* Encode: the whole thing
****************************************************************************/
static block_t *Encode( encoder_t *p_enc, subpicture_t *p_subpic )
{
subpicture_t *p_temp = NULL;
subpicture_region_t *p_region = NULL;
bs_t bits, *s = &bits;
block_t *p_block;
if( !p_subpic || !p_subpic->p_region ) return 0;
if( !p_subpic || !p_subpic->p_region ) return NULL;
/* FIXME: this is a hack to convert VLC_FOURCC('Y','U','V','A') into
* VLC_FOURCC('Y','U','V','P')
*/
p_region = p_subpic->p_region;
if( p_region->fmt.i_chroma == VLC_FOURCC('Y','U','V','A') )
{
p_temp = YuvaYuvp( p_enc, p_subpic );
if( !p_temp )
{
msg_Dbg( p_enc, "no picture in subpicture" );
return NULL;
}
p_region = p_subpic->p_region;
}
/* Sanity check */
if( !p_region ) return NULL;
if( p_region->fmt.i_chroma != VLC_FOURCC('T','E','X','T') &&
p_region->fmt.i_chroma != VLC_FOURCC('Y','U','V','P') ) return NULL;
if( p_region->fmt.p_palette &&
( p_region->fmt.p_palette->i_entries != 4 ) &&
( p_region->fmt.p_palette->i_entries != 16 ) &&
( p_region->fmt.p_palette->i_entries != 256 ) )
{
msg_Err( p_enc, "subpicture palette (%d) not handled",
p_region->fmt.p_palette->i_entries );
return NULL;
}
/* End of hack */
#if DEBUG_DVBSUB
msg_Dbg( p_enc, "encoding subpicture" );
#endif
......
This diff is collapsed.
This diff is collapsed.
......@@ -16,4 +16,5 @@ SOURCES_marq = marq.c
SOURCES_rss = rss.c
SOURCES_motiondetect = motiondetect.c
SOURCES_rv32 = rv32.c
SOURCES_osdmenu = osdmenu.c
noinst_HEADERS += filter_common.h
This diff is collapsed.
DIST_SUBDIRS = interface playlist input audio_output video_output stream_output misc
DIST_SUBDIRS = interface playlist input audio_output video_output stream_output misc osd
EXTRA_DIST = misc/modules_builtin.h.in
......@@ -107,6 +107,7 @@
#include "vlc_vlm.h"
#include "vlc_image.h"
#include "vlc_osd.h"
#if defined( _MSC_VER ) && defined( UNDER_CE )
# include "modules_builtin_evc.h"
......
......@@ -55,6 +55,7 @@
#include "vlc_vod.h"
#include "vlc_tls.h"
#include "vlc_xml.h"
#include "vlc_osd.h"
/*****************************************************************************
* Local prototypes
......@@ -207,6 +208,10 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type )
i_size = sizeof( announce_handler_t );
psz_type = "announce handler";
break;
case VLC_OBJECT_OSDMENU:
i_size = sizeof( osd_menu_t );
psz_type = "osd menu";
break;
default:
i_size = i_type > 0
? i_type > (int)sizeof(vlc_object_t)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment