Commit f976d6ae authored by Christophe Massiot's avatar Christophe Massiot

* ALL: converted the video output module "picture" to a stream output

   module "mosaic-bridge".
parent 0ae97f35
...@@ -986,7 +986,7 @@ if test "${SYS}" != "mingwce"; then ...@@ -986,7 +986,7 @@ if test "${SYS}" != "mingwce"; then
VLC_ADD_PLUGINS([externrun]) VLC_ADD_PLUGINS([externrun])
VLC_ADD_PLUGINS([access_fake access_filter_timeshift]) VLC_ADD_PLUGINS([access_fake access_filter_timeshift])
VLC_ADD_PLUGINS([gestures rc telnet hotkeys netsync showintf time marq sap shout]) VLC_ADD_PLUGINS([gestures rc telnet hotkeys netsync showintf time marq sap shout])
VLC_ADD_PLUGINS([picture mosaic wall motiondetect clone crop]) VLC_ADD_PLUGINS([mosaic wall motiondetect clone crop])
VLC_ADD_PLUGINS([i420_yuy2 i422_yuy2 i420_ymga]) VLC_ADD_PLUGINS([i420_yuy2 i422_yuy2 i420_ymga])
VLC_ADD_PLUGINS([aout_file linear_resampler bandlimited_resampler]) VLC_ADD_PLUGINS([aout_file linear_resampler bandlimited_resampler])
VLC_ADD_PLUGINS([float32_mixer spdif_mixer simple_channel_mixer]) VLC_ADD_PLUGINS([float32_mixer spdif_mixer simple_channel_mixer])
...@@ -1227,7 +1227,7 @@ then ...@@ -1227,7 +1227,7 @@ then
VLC_ADD_PLUGINS([packetizer_copy]) VLC_ADD_PLUGINS([packetizer_copy])
VLC_ADD_PLUGINS([stream_out_dummy stream_out_standard stream_out_es stream_out_rtp stream_out_description vod_rtsp]) VLC_ADD_PLUGINS([stream_out_dummy stream_out_standard stream_out_es stream_out_rtp stream_out_description vod_rtsp])
VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode stream_out_bridge]) VLC_ADD_PLUGINS([stream_out_duplicate stream_out_gather stream_out_display stream_out_transcode stream_out_bridge stream_out_mosaic_bridge])
# VLC_ADD_PLUGINS([stream_out_transrate]) # VLC_ADD_PLUGINS([stream_out_transrate])
AC_DEFINE(ENABLE_SOUT, 1, Define if you want the stream output support) AC_DEFINE(ENABLE_SOUT, 1, Define if you want the stream output support)
...@@ -2533,7 +2533,7 @@ AC_ARG_ENABLE(speex, ...@@ -2533,7 +2533,7 @@ AC_ARG_ENABLE(speex,
if test "${enable_speex}" != "no" if test "${enable_speex}" != "no"
then then
AC_CHECK_HEADERS(speex/speex.h, [ AC_CHECK_HEADERS(speex/speex.h, [
LDFLAGS="${LDFLAGS_save} ${LDFLAGS_toolame}" LDFLAGS="${LDFLAGS_save} ${LDFLAGS_speex}"
AC_CHECK_LIB(speex, speex_decode_int, [ AC_CHECK_LIB(speex, speex_decode_int, [
VLC_ADD_PLUGINS([speex]) VLC_ADD_PLUGINS([speex])
VLC_ADD_LDFLAGS([speex],[-lspeex]) ], VLC_ADD_LDFLAGS([speex],[-lspeex]) ],
......
...@@ -11,3 +11,4 @@ SOURCES_stream_out_gather = gather.c ...@@ -11,3 +11,4 @@ SOURCES_stream_out_gather = gather.c
SOURCES_stream_out_rtp = rtp.c SOURCES_stream_out_rtp = rtp.c
SOURCES_stream_out_switcher = switcher.c SOURCES_stream_out_switcher = switcher.c
SOURCES_stream_out_bridge = bridge.c SOURCES_stream_out_bridge = bridge.c
SOURCES_stream_out_mosaic_bridge = mosaic_bridge.c
...@@ -58,7 +58,7 @@ vlc_module_begin(); ...@@ -58,7 +58,7 @@ vlc_module_begin();
set_shortname( _("Bridge")); set_shortname( _("Bridge"));
set_description( _("Bridge stream output")); set_description( _("Bridge stream output"));
add_submodule(); add_submodule();
set_section( N_("Bridge out"),NULL); set_section( N_("Bridge out"), NULL );
set_capability( "sout stream", 50 ); set_capability( "sout stream", 50 );
add_shortcut( "bridge-out" ); add_shortcut( "bridge-out" );
/* Only usable with VLM. No category so not in gui preferences /* Only usable with VLM. No category so not in gui preferences
...@@ -69,12 +69,12 @@ vlc_module_begin(); ...@@ -69,12 +69,12 @@ vlc_module_begin();
set_callbacks( OpenOut, CloseOut ); set_callbacks( OpenOut, CloseOut );
add_submodule(); add_submodule();
set_section( N_("Bridge in"),NULL); set_section( N_("Bridge in"), NULL );
set_capability( "sout stream", 50 ); set_capability( "sout stream", 50 );
add_shortcut( "bridge-in" ); add_shortcut( "bridge-in" );
/*set_category( CAT_SOUT ); /*set_category( CAT_SOUT );
set_subcategory( SUBCAT_SOUT_STREAM );*/ set_subcategory( SUBCAT_SOUT_STREAM );*/
add_integer( SOUT_CFG_PREFIX_IN "delay", 100, NULL, DELAY_TEXT, add_integer( SOUT_CFG_PREFIX_IN "delay", 0, NULL, DELAY_TEXT,
DELAY_LONGTEXT, VLC_FALSE ); DELAY_LONGTEXT, VLC_FALSE );
add_integer( SOUT_CFG_PREFIX_IN "id-offset", 8192, NULL, ID_OFFSET_TEXT, add_integer( SOUT_CFG_PREFIX_IN "id-offset", 8192, NULL, ID_OFFSET_TEXT,
ID_OFFSET_LONGTEXT, VLC_FALSE ); ID_OFFSET_LONGTEXT, VLC_FALSE );
...@@ -109,7 +109,6 @@ typedef struct bridged_es_t ...@@ -109,7 +109,6 @@ typedef struct bridged_es_t
block_t *p_block; block_t *p_block;
block_t **pp_last; block_t **pp_last;
vlc_bool_t b_empty; vlc_bool_t b_empty;
int i_id;
/* bridge in part */ /* bridge in part */
sout_stream_id_t *id; sout_stream_id_t *id;
...@@ -150,9 +149,9 @@ static bridge_t *__GetBridge( vlc_object_t *p_object ) ...@@ -150,9 +149,9 @@ static bridge_t *__GetBridge( vlc_object_t *p_object )
typedef struct out_sout_stream_sys_t typedef struct out_sout_stream_sys_t
{ {
vlc_mutex_t *p_lock; vlc_mutex_t *p_lock;
bridged_es_t *p_es;
int i_id; int i_id;
vlc_bool_t b_inited; vlc_bool_t b_inited;
int i_position;
} out_sout_stream_sys_t; } out_sout_stream_sys_t;
/***************************************************************************** /*****************************************************************************
...@@ -160,7 +159,7 @@ typedef struct out_sout_stream_sys_t ...@@ -160,7 +159,7 @@ typedef struct out_sout_stream_sys_t
*****************************************************************************/ *****************************************************************************/
static int OpenOut( vlc_object_t *p_this ) static int OpenOut( vlc_object_t *p_this )
{ {
sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_t *p_stream = (sout_stream_t *)p_this;
out_sout_stream_sys_t *p_sys; out_sout_stream_sys_t *p_sys;
vlc_value_t val; vlc_value_t val;
...@@ -182,7 +181,6 @@ static int OpenOut( vlc_object_t *p_this ) ...@@ -182,7 +181,6 @@ static int OpenOut( vlc_object_t *p_this )
p_stream->p_sys = (sout_stream_sys_t *)p_sys; p_stream->p_sys = (sout_stream_sys_t *)p_sys;
/* update p_sout->i_out_pace_nocontrol */
p_stream->p_sout->i_out_pace_nocontrol++; p_stream->p_sout->i_out_pace_nocontrol++;
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -243,14 +241,12 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -243,14 +241,12 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt )
p_bridge->pp_es = realloc( p_bridge->pp_es, p_bridge->pp_es = realloc( p_bridge->pp_es,
(p_bridge->i_es_num + 1) (p_bridge->i_es_num + 1)
* sizeof(bridged_es_t *) ); * sizeof(bridged_es_t *) );
p_sys->i_position = p_bridge->i_es_num;
p_bridge->i_es_num++; p_bridge->i_es_num++;
p_bridge->pp_es[i] = malloc( sizeof(bridged_es_t) ); p_bridge->pp_es[i] = malloc( sizeof(bridged_es_t) );
} }
else
p_sys->i_position = i;
p_es = p_bridge->pp_es[ p_sys->i_position ]; p_sys->p_es = p_es = p_bridge->pp_es[i];
p_es->fmt = *p_fmt; p_es->fmt = *p_fmt;
p_es->fmt.i_id = p_sys->i_id; p_es->fmt.i_id = p_sys->i_id;
p_es->p_block = NULL; p_es->p_block = NULL;
...@@ -262,7 +258,7 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -262,7 +258,7 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt )
p_es->b_changed = VLC_TRUE; p_es->b_changed = VLC_TRUE;
msg_Dbg( p_stream, "bridging out input codec=%4.4s id=%d pos=%d", msg_Dbg( p_stream, "bridging out input codec=%4.4s id=%d pos=%d",
(char*)&p_es->fmt.i_codec, p_es->fmt.i_id, p_sys->i_position ); (char*)&p_es->fmt.i_codec, p_es->fmt.i_id, i );
vlc_mutex_unlock( p_sys->p_lock ); vlc_mutex_unlock( p_sys->p_lock );
...@@ -272,7 +268,6 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -272,7 +268,6 @@ static sout_stream_id_t * AddOut( sout_stream_t *p_stream, es_format_t *p_fmt )
static int DelOut( sout_stream_t *p_stream, sout_stream_id_t *id ) static int DelOut( sout_stream_t *p_stream, sout_stream_id_t *id )
{ {
out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys; out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys;
bridge_t *p_bridge;
bridged_es_t *p_es; bridged_es_t *p_es;
if ( !p_sys->b_inited ) if ( !p_sys->b_inited )
...@@ -282,8 +277,7 @@ static int DelOut( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -282,8 +277,7 @@ static int DelOut( sout_stream_t *p_stream, sout_stream_id_t *id )
vlc_mutex_lock( p_sys->p_lock ); vlc_mutex_lock( p_sys->p_lock );
p_bridge = GetBridge( p_stream ); p_es = p_sys->p_es;
p_es = p_bridge->pp_es[ p_sys->i_position ];
p_es->b_empty = VLC_TRUE; p_es->b_empty = VLC_TRUE;
block_ChainRelease( p_es->p_block ); block_ChainRelease( p_es->p_block );
...@@ -299,7 +293,6 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -299,7 +293,6 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id,
block_t *p_buffer ) block_t *p_buffer )
{ {
out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys; out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys;
bridge_t *p_bridge;
bridged_es_t *p_es; bridged_es_t *p_es;
if ( (out_sout_stream_sys_t *)id != p_sys ) if ( (out_sout_stream_sys_t *)id != p_sys )
...@@ -310,8 +303,7 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -310,8 +303,7 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id,
vlc_mutex_lock( p_sys->p_lock ); vlc_mutex_lock( p_sys->p_lock );
p_bridge = GetBridge( p_stream ); p_es = p_sys->p_es;
p_es = p_bridge->pp_es[ p_sys->i_position ];
*p_es->pp_last = p_buffer; *p_es->pp_last = p_buffer;
while ( p_buffer != NULL ) while ( p_buffer != NULL )
{ {
......
/***************************************************************************** /*****************************************************************************
* picture.c: * mosaic_bridge.c:
***************************************************************************** *****************************************************************************
* Copyright (C) 2004-2005 VideoLAN * Copyright (C) 2004-2005 VideoLAN
* $Id$ * $Id$
...@@ -30,32 +30,33 @@ ...@@ -30,32 +30,33 @@
#include <string.h> /* strerror() */ #include <string.h> /* strerror() */
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/vout.h> #include <vlc/sout.h>
#include <vlc/decoder.h>
#include "vlc_image.h" #include "vlc_image.h"
#include "picture.h" #include "../video_filter/mosaic.h"
/***************************************************************************** /*****************************************************************************
* Local structures * Local structures
*****************************************************************************/ *****************************************************************************/
struct vout_sys_t struct sout_stream_sys_t
{ {
picture_vout_t *p_picture_vout; bridged_es_t *p_es;
vlc_mutex_t *p_lock; vlc_mutex_t *p_lock;
int i_picture_pos; /* picture position in p_picture_vout */ decoder_t *p_decoder;
image_handler_t *p_image; /* filters for resizing */ image_handler_t *p_image; /* filter for resizing */
#ifdef IMAGE_2PASSES
image_handler_t *p_image2;
#endif
int i_height, i_width; int i_height, i_width;
mtime_t i_last_pic; char *psz_id;
vlc_bool_t b_inited;
}; };
/* Delay after which the picture is blanked out if there hasn't been any #define PICTURE_RING_SIZE 64
* new picture. */ struct decoder_owner_sys_t
#define BLANK_DELAY I64C(1000000) {
picture_t *pp_pics[PICTURE_RING_SIZE];
};
typedef void (* pf_release_t)( picture_t * ); typedef void (* pf_release_t)( picture_t * );
static void ReleasePicture( picture_t *p_pic ) static void ReleasePicture( picture_t *p_pic )
...@@ -83,10 +84,14 @@ static void ReleasePicture( picture_t *p_pic ) ...@@ -83,10 +84,14 @@ static void ReleasePicture( picture_t *p_pic )
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static int Init ( vout_thread_t * ); static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
static void End ( vout_thread_t * ); static int Del ( sout_stream_t *, sout_stream_id_t * );
static int Manage ( vout_thread_t * ); static int Send( sout_stream_t *, sout_stream_id_t *, block_t * );
static void Display ( vout_thread_t *, picture_t * );
static void video_del_buffer( decoder_t *, picture_t * );
static picture_t *video_new_buffer( decoder_t * );
static void video_link_picture_decoder( decoder_t *, picture_t * );
static void video_unlink_picture_decoder( decoder_t *, picture_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -102,226 +107,231 @@ static void Display ( vout_thread_t *, picture_t * ); ...@@ -102,226 +107,231 @@ static void Display ( vout_thread_t *, picture_t * );
#define HEIGHT_LONGTEXT N_( \ #define HEIGHT_LONGTEXT N_( \
"Allows you to specify the output video height." ) "Allows you to specify the output video height." )
vlc_module_begin(); #define SOUT_CFG_PREFIX "sout-mosaic-bridge-"
set_shortname( _( "Picture" ) );
set_description(_("VLC internal picture video output") );
set_capability( "video output", 0 );
add_string( "picture-id", "Id", NULL, ID_TEXT, ID_LONGTEXT, VLC_FALSE ); vlc_module_begin();
add_integer( "picture-width", 0, NULL, WIDTH_TEXT, set_shortname( _( "Mosaic bridge" ) );
set_description(_("Mosaic bridge stream output") );
set_capability( "sout stream", 0 );
add_shortcut( "mosaic-bridge" );
add_string( SOUT_CFG_PREFIX "id", "Id", NULL, ID_TEXT, ID_LONGTEXT,
VLC_FALSE );
add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
WIDTH_LONGTEXT, VLC_TRUE ); WIDTH_LONGTEXT, VLC_TRUE );
add_integer( "picture-height", 0, NULL, HEIGHT_TEXT, add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
HEIGHT_LONGTEXT, VLC_TRUE ); HEIGHT_LONGTEXT, VLC_TRUE );
set_callbacks( Open, Close ); set_callbacks( Open, Close );
var_Create( p_module->p_libvlc, "picture-lock", VLC_VAR_MUTEX ); var_Create( p_module->p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
vlc_module_end(); vlc_module_end();
static const char *ppsz_sout_options[] = {
"id", "width", "height", NULL
};
/***************************************************************************** /*****************************************************************************
* Open : allocate video thread output method * Open
*****************************************************************************/ *****************************************************************************/
static int Open( vlc_object_t *p_this ) static int Open( vlc_object_t *p_this )
{ {
vout_thread_t *p_vout = (vout_thread_t *)p_this; sout_stream_t *p_stream = (sout_stream_t *)p_this;
vout_sys_t *p_sys; sout_stream_sys_t *p_sys;
libvlc_t *p_libvlc = p_vout->p_libvlc; libvlc_t *p_libvlc = p_this->p_libvlc;
picture_vout_t *p_picture_vout = NULL; vlc_value_t val;
picture_vout_e_t *p_pic;
vlc_value_t val, lockval;
p_sys = p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_sys == NULL )
{
msg_Err( p_vout, "out of memory" );
return VLC_ENOMEM;
}
var_Get( p_libvlc, "picture-lock", &lockval );
p_sys->p_lock = lockval.p_address;
vlc_mutex_lock( p_sys->p_lock );
p_sys->i_picture_pos = -1;
if( var_Get( p_libvlc, "p_picture_vout", &val ) != VLC_SUCCESS )
{
p_picture_vout = malloc( sizeof( struct picture_vout_t ) );
if( p_picture_vout == NULL )
{
msg_Err( p_vout, "out of memory" );
return VLC_ENOMEM;
}
var_Create( p_libvlc, "p_picture_vout", VLC_VAR_ADDRESS );
val.p_address = p_picture_vout;
var_Set( p_libvlc, "p_picture_vout", val );
p_picture_vout->i_picture_num = 0;
p_picture_vout->p_pic = NULL;
}
else
{
int i;
p_picture_vout = val.p_address;
for ( i = 0; i < p_picture_vout->i_picture_num; i++ )
{
if ( p_picture_vout->p_pic[i].i_status == PICTURE_VOUT_E_AVAILABLE )
break;
}
if ( i != p_picture_vout->i_picture_num ) sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
p_sys->i_picture_pos = i; p_stream->p_cfg );
}
p_sys->p_picture_vout = p_picture_vout; p_sys = malloc( sizeof( sout_stream_sys_t ) );
p_stream->p_sys = p_sys;
p_sys->b_inited = VLC_FALSE;
if ( p_sys->i_picture_pos == -1 ) var_Get( p_libvlc, "mosaic-lock", &val );
{ p_sys->p_lock = val.p_address;
p_picture_vout->p_pic = realloc( p_picture_vout->p_pic,
(p_picture_vout->i_picture_num + 1)
* sizeof(picture_vout_e_t) );
p_sys->i_picture_pos = p_picture_vout->i_picture_num;
p_picture_vout->i_picture_num++;
}
p_pic = &p_picture_vout->p_pic[p_sys->i_picture_pos]; var_Get( p_stream, SOUT_CFG_PREFIX "id", &val );
p_pic->p_picture = NULL; p_sys->psz_id = val.psz_string;
p_pic->i_status = PICTURE_VOUT_E_OCCUPIED;
var_Create( p_vout, "picture-id", VLC_VAR_STRING ); var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
var_Change( p_vout, "picture-id", VLC_VAR_INHERITVALUE, &val, NULL );
p_pic->psz_id = val.psz_string;
vlc_mutex_unlock( p_sys->p_lock );
var_Create( p_vout, "picture-height", VLC_VAR_INTEGER );
var_Change( p_vout, "picture-height", VLC_VAR_INHERITVALUE, &val, NULL );
p_sys->i_height = val.i_int; p_sys->i_height = val.i_int;
var_Create( p_vout, "picture-width", VLC_VAR_INTEGER ); var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
var_Change( p_vout, "picture-width", VLC_VAR_INHERITVALUE, &val, NULL );
p_sys->i_width = val.i_int; p_sys->i_width = val.i_int;
if ( p_sys->i_height || p_sys->i_width ) if ( p_sys->i_height || p_sys->i_width )
{ {
p_sys->p_image = image_HandlerCreate( p_vout ); p_sys->p_image = image_HandlerCreate( p_stream );
#ifdef IMAGE_2PASSES
p_sys->p_image2 = image_HandlerCreate( p_vout );
#endif
} }
p_sys->i_last_pic = 0; p_stream->pf_add = Add;
p_stream->pf_del = Del;
p_stream->pf_send = Send;
p_vout->pf_init = Init; p_stream->p_sout->i_out_pace_nocontrol++;
p_vout->pf_end = End;
p_vout->pf_manage = Manage;
p_vout->pf_render = NULL;
p_vout->pf_display = Display;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* Init * Close
*****************************************************************************/ *****************************************************************************/
static int Init( vout_thread_t *p_vout ) static void Close( vlc_object_t * p_this )
{ {
picture_t *p_pic; sout_stream_t *p_stream = (sout_stream_t*)p_this;
int i_index; sout_stream_sys_t *p_sys = p_stream->p_sys;
I_OUTPUTPICTURES = 0; p_stream->p_sout->i_out_pace_nocontrol--;
p_vout->output.i_chroma = p_vout->render.i_chroma; if ( p_sys->psz_id )
p_vout->output.i_width = p_vout->render.i_width; free( p_sys->psz_id );
p_vout->output.i_height = p_vout->render.i_height;
p_vout->output.i_aspect = p_vout->render.i_aspect;
while( VLC_TRUE ) free( p_sys );
{ }
p_pic = NULL;
for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
{ {
if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) sout_stream_sys_t *p_sys = p_stream->p_sys;
bridge_t *p_bridge;
bridged_es_t *p_es;
int i;
if ( p_sys->b_inited )
{ {
p_pic = p_vout->p_picture + i_index; return NULL;
break;
}
} }
if( p_pic == NULL ) /* Create decoder object */
p_sys->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
vlc_object_attach( p_sys->p_decoder, p_stream );
p_sys->p_decoder->p_module = NULL;
p_sys->p_decoder->fmt_in = *p_fmt;
p_sys->p_decoder->b_pace_control = VLC_FALSE;
p_sys->p_decoder->fmt_out = p_sys->p_decoder->fmt_in;
p_sys->p_decoder->fmt_out.i_extra = 0;
p_sys->p_decoder->fmt_out.p_extra = 0;
p_sys->p_decoder->pf_decode_video = 0;
p_sys->p_decoder->pf_vout_buffer_new = video_new_buffer;
p_sys->p_decoder->pf_vout_buffer_del = video_del_buffer;
p_sys->p_decoder->pf_picture_link = video_link_picture_decoder;
p_sys->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
p_sys->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
for( i = 0; i < PICTURE_RING_SIZE; i++ )
p_sys->p_decoder->p_owner->pp_pics[i] = 0;
//p_sys->p_decoder->p_cfg = p_sys->p_video_cfg;
p_sys->p_decoder->p_module =
module_Need( p_sys->p_decoder, "decoder", "$codec", 0 );
if( !p_sys->p_decoder->p_module )
{ {
return VLC_SUCCESS; msg_Err( p_stream, "cannot find decoder" );
vlc_object_detach( p_sys->p_decoder );
vlc_object_destroy( p_sys->p_decoder );
return NULL;
} }
vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic, p_sys->b_inited = VLC_TRUE;
p_vout->output.i_chroma, vlc_mutex_lock( p_sys->p_lock );
p_vout->output.i_width, p_vout->output.i_height,
p_vout->output.i_aspect );
if( p_pic->i_planes == 0 ) p_bridge = GetBridge( p_stream );
if ( p_bridge == NULL )
{ {
return VLC_EGENERIC; libvlc_t *p_libvlc = p_stream->p_libvlc;
} vlc_value_t val;
p_pic->i_status = DESTROYED_PICTURE; p_bridge = malloc( sizeof( bridge_t ) );
p_pic->i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; var_Create( p_libvlc, "mosaic-struct", VLC_VAR_ADDRESS );
val.p_address = p_bridge;
var_Set( p_libvlc, "mosaic-struct", val );
I_OUTPUTPICTURES++; p_bridge->i_es_num = 0;
p_bridge->pp_es = NULL;
}
//return VLC_SUCCESS; for ( i = 0; i < p_bridge->i_es_num; i++ )
{
if ( p_bridge->pp_es[i]->b_empty )
break;
} }
} if ( i == p_bridge->i_es_num )
{
p_bridge->pp_es = realloc( p_bridge->pp_es,
(p_bridge->i_es_num + 1)
* sizeof(bridged_es_t *) );
p_bridge->i_es_num++;
p_bridge->pp_es[i] = malloc( sizeof(bridged_es_t) );
}
/***************************************************************************** p_sys->p_es = p_es = p_bridge->pp_es[i];
* End
*****************************************************************************/ //p_es->fmt = *p_fmt;
static void End( vout_thread_t *p_vout ) p_es->psz_id = p_sys->psz_id;
{ p_es->p_picture = NULL;
return; p_es->pp_last = &p_es->p_picture;
p_es->b_empty = VLC_FALSE;
vlc_mutex_unlock( p_sys->p_lock );
msg_Dbg( p_stream, "mosaic bridge id=%s pos=%d", p_es->psz_id, i );
return (sout_stream_id_t *)p_sys;
} }
/***************************************************************************** static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
* Close
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{ {
vout_thread_t *p_vout = (vout_thread_t *)p_this; sout_stream_sys_t *p_sys = p_stream->p_sys;
vout_sys_t *p_sys = p_vout->p_sys; bridge_t *p_bridge;
picture_vout_t *p_picture_vout = p_sys->p_picture_vout; bridged_es_t *p_es;
picture_vout_e_t *p_pic; vlc_bool_t b_last_es = VLC_TRUE;
vlc_bool_t b_last_picture = VLC_TRUE;
int i; int i;
if ( !p_sys->b_inited )
{
return VLC_SUCCESS;
}
if ( p_sys->p_decoder )
{
if( p_sys->p_decoder->p_module )
module_Unneed( p_sys->p_decoder, p_sys->p_decoder->p_module );
vlc_object_detach( p_sys->p_decoder );
vlc_object_destroy( p_sys->p_decoder );
}
vlc_mutex_lock( p_sys->p_lock ); vlc_mutex_lock( p_sys->p_lock );
p_pic = &p_picture_vout->p_pic[p_sys->i_picture_pos];
if( p_pic->p_picture ) p_bridge = GetBridge( p_stream );
p_es = p_sys->p_es;
p_es->b_empty = VLC_TRUE;
while ( p_es->p_picture )
{ {
p_pic->p_picture->pf_release( p_pic->p_picture ); picture_t *p_next = p_es->p_picture->p_next;
p_pic->p_picture = NULL; p_es->p_picture->pf_release( p_es->p_picture );
p_es->p_picture = p_next;
} }
p_pic->i_status = PICTURE_VOUT_E_AVAILABLE;
if( p_pic->psz_id )
free( p_pic->psz_id );
for( i = 0; i < p_picture_vout->i_picture_num; i ++) for ( i = 0; i < p_bridge->i_es_num; i++ )
{ {
if( p_picture_vout->p_pic[i].i_status == PICTURE_VOUT_E_OCCUPIED ) if ( !p_bridge->pp_es[i]->b_empty )
{ {
b_last_picture = VLC_FALSE; b_last_es = VLC_FALSE;
break; break;
} }
} }
if( b_last_picture ) if ( b_last_es )
{ {
free( p_picture_vout->p_pic ); libvlc_t *p_libvlc = p_stream->p_libvlc;
free( p_picture_vout ); for ( i = 0; i < p_bridge->i_es_num; i++ )
var_Destroy( p_this->p_libvlc, "p_picture_vout" ); free( p_bridge->pp_es[i] );
free( p_bridge->pp_es );
free( p_bridge );
var_Destroy( p_libvlc, "mosaic-struct" );
} }
vlc_mutex_unlock( p_sys->p_lock ); vlc_mutex_unlock( p_sys->p_lock );
...@@ -329,123 +339,51 @@ static void Close( vlc_object_t *p_this ) ...@@ -329,123 +339,51 @@ static void Close( vlc_object_t *p_this )
if ( p_sys->i_height || p_sys->i_width ) if ( p_sys->i_height || p_sys->i_width )
{ {
image_HandlerDelete( p_sys->p_image ); image_HandlerDelete( p_sys->p_image );
#ifdef IMAGE_2PASSES
image_HandlerDelete( p_sys->p_image2 );
#endif
} }
free( p_sys ); p_sys->b_inited = VLC_FALSE;
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* PushPicture : push a picture in the p_picture_vout structure * PushPicture : push a picture in the mosaic-struct structure
*****************************************************************************/ *****************************************************************************/
static void PushPicture( vout_thread_t *p_vout, picture_t *p_picture ) static void PushPicture( sout_stream_t *p_stream, picture_t *p_picture )
{ {
vout_sys_t *p_sys = p_vout->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
picture_vout_t *p_picture_vout = p_sys->p_picture_vout; bridged_es_t *p_es = p_sys->p_es;
picture_vout_e_t *p_pic;
vlc_mutex_lock( p_sys->p_lock ); vlc_mutex_lock( p_sys->p_lock );
p_pic = &p_picture_vout->p_pic[p_sys->i_picture_pos];
if( p_pic->p_picture != NULL ) *p_es->pp_last = p_picture;
{ p_picture->p_next = NULL;
p_pic->p_picture->pf_release( p_pic->p_picture ); p_es->pp_last = &p_picture->p_next;
}
p_pic->p_picture = p_picture;
vlc_mutex_unlock( p_sys->p_lock ); vlc_mutex_unlock( p_sys->p_lock );
} }
/***************************************************************************** static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
* Manage block_t *p_buffer )
*****************************************************************************/
static int Manage( vout_thread_t *p_vout )
{ {
vout_sys_t *p_sys = p_vout->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
picture_t *p_pic;
if ( mdate() - p_sys->i_last_pic > BLANK_DELAY )
{
/* Display black */
#if 0
picture_t *p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
int i;
if ( p_sys->i_height || p_sys->i_width ) if ( (sout_stream_sys_t *)id != p_sys )
{
vout_AllocatePicture( p_vout, p_new_pic,
VLC_FOURCC('Y','U','V','A'),
p_sys->i_width, p_sys->i_height,
p_vout->render.i_aspect );
}
else
{ {
vout_AllocatePicture( p_vout, p_new_pic, p_vout->render.i_chroma, block_ChainRelease( p_buffer );
p_vout->render.i_width, return VLC_SUCCESS;
p_vout->render.i_height,
p_vout->render.i_aspect );
} }
p_new_pic->i_refcount++; while ( (p_pic = p_sys->p_decoder->pf_decode_video( p_sys->p_decoder,
p_new_pic->i_status = DESTROYED_PICTURE; &p_buffer )) )
p_new_pic->i_type = DIRECT_PICTURE;
p_new_pic->pf_release = ReleasePicture;
for ( i = 0; i < p_pic->i_planes; i++ )
{ {
/* This assumes planar YUV format */
p_vout->p_vlc->pf_memset( p_pic->p[i].p_pixels, i ? 0x80 : 0,
p_pic->p[i].i_lines
* p_pic->p[i].i_pitch );
}
PushPicture( p_vout, p_new_pic );
#else
PushPicture( p_vout, NULL );
#endif
p_sys->i_last_pic = INT64_MAX;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* Display
*****************************************************************************/
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
vout_sys_t *p_sys = p_vout->p_sys;
picture_t *p_new_pic; picture_t *p_new_pic;
if ( p_sys->i_height || p_sys->i_width ) if ( p_sys->i_height || p_sys->i_width )
{ {
video_format_t fmt_out = {0}, fmt_in = {0}; video_format_t fmt_out = {0}, fmt_in = {0};
#ifdef IMAGE_2PASSES fmt_in = p_sys->p_decoder->fmt_out.video;
vide_format_t fmt_middle = {0};
picture_t *p_new_pic2;
#endif
fmt_in = p_vout->fmt_in;
#ifdef IMAGE_2PASSES
fmt_middle.i_chroma = p_vout->render.i_chroma;
fmt_middle.i_width = p_vout->p_sys->i_width;
fmt_middle.i_height = p_vout->p_sys->i_height;
fmt_middle.i_visible_width = fmt_middle.i_width;
fmt_middle.i_visible_height = fmt_middle.i_height;
p_new_pic2 = image_Convert( p_vout->p_sys->p_image2,
p_pic, &fmt_in, &fmt_middle );
if ( p_new_pic2 == NULL )
{
msg_Err( p_vout, "image resizing failed %dx%d->%dx%d %4.4s",
p_vout->render.i_width, p_vout->render.i_height,
fmt_middle.i_width, fmt_middle.i_height,
(char *)&p_vout->render.i_chroma);
return;
}
#endif
fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A'); fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
fmt_out.i_width = p_sys->i_width; fmt_out.i_width = p_sys->i_width;
...@@ -453,36 +391,122 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -453,36 +391,122 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic )
fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_width = fmt_out.i_width;
fmt_out.i_visible_height = fmt_out.i_height; fmt_out.i_visible_height = fmt_out.i_height;
#ifdef IMAGE_2PASSES p_new_pic = image_Convert( p_sys->p_image,
p_new_pic = image_Convert( p_vout->p_sys->p_image,
p_new_pic2, &fmt_middle, &fmt_out );
p_new_pic2->pf_release( p_new_pic2 );
#else
p_new_pic = image_Convert( p_vout->p_sys->p_image,
p_pic, &fmt_in, &fmt_out ); p_pic, &fmt_in, &fmt_out );
#endif
if ( p_new_pic == NULL ) if ( p_new_pic == NULL )
{ {
msg_Err( p_vout, "image conversion failed" ); msg_Err( p_stream, "image conversion failed" );
return; continue;
} }
} }
else else
{ {
p_new_pic = (picture_t*)malloc( sizeof(picture_t) ); p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
vout_AllocatePicture( p_vout, p_new_pic, p_pic->format.i_chroma, vout_AllocatePicture( p_stream, p_new_pic, p_pic->format.i_chroma,
p_pic->format.i_width, p_pic->format.i_height, p_pic->format.i_width, p_pic->format.i_height,
p_vout->render.i_aspect ); p_sys->p_decoder->fmt_out.video.i_aspect );
vout_CopyPicture( p_vout, p_new_pic, p_pic ); vout_CopyPicture( p_stream, p_new_pic, p_pic );
} }
p_pic->pf_release( p_pic );
p_new_pic->i_refcount = 1; p_new_pic->i_refcount = 1;
p_new_pic->i_status = DESTROYED_PICTURE; p_new_pic->i_status = DESTROYED_PICTURE;
p_new_pic->i_type = DIRECT_PICTURE; p_new_pic->i_type = DIRECT_PICTURE;
p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release; p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release;
p_new_pic->pf_release = ReleasePicture; p_new_pic->pf_release = ReleasePicture;
p_new_pic->date = p_pic->date;
PushPicture( p_stream, p_new_pic );
}
PushPicture( p_vout, p_new_pic ); return VLC_SUCCESS;
p_sys->i_last_pic = p_pic->date; }
struct picture_sys_t
{
vlc_object_t *p_owner;
};
static void video_release_buffer( picture_t *p_pic )
{
if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
{
video_del_buffer( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
}
else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
} }
static picture_t *video_new_buffer( decoder_t *p_dec )
{
picture_t **pp_ring = p_dec->p_owner->pp_pics;
picture_t *p_pic;
int i;
/* Find an empty space in the picture ring buffer */
for( i = 0; i < PICTURE_RING_SIZE; i++ )
{
if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
{
pp_ring[i]->i_status = RESERVED_PICTURE;
return pp_ring[i];
}
}
for( i = 0; i < PICTURE_RING_SIZE; i++ )
{
if( pp_ring[i] == 0 ) break;
}
if( i == PICTURE_RING_SIZE )
{
msg_Err( p_dec, "decoder/filter is leaking pictures, "
"resetting its ring buffer" );
for( i = 0; i < PICTURE_RING_SIZE; i++ )
{
pp_ring[i]->pf_release( pp_ring[i] );
}
i = 0;
}
p_pic = malloc( sizeof(picture_t) );
p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
p_dec->fmt_out.video.i_chroma,
p_dec->fmt_out.video.i_width,
p_dec->fmt_out.video.i_height,
p_dec->fmt_out.video.i_aspect );
if( !p_pic->i_planes )
{
free( p_pic );
return 0;
}
p_pic->pf_release = video_release_buffer;
p_pic->p_sys = malloc( sizeof(picture_sys_t) );
p_pic->p_sys->p_owner = VLC_OBJECT(p_dec);
p_pic->i_status = RESERVED_PICTURE;
pp_ring[i] = p_pic;
return p_pic;
}
static void video_del_buffer( decoder_t *p_this, picture_t *p_pic )
{
p_pic->i_refcount = 0;
p_pic->i_status = DESTROYED_PICTURE;
}
static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
{
p_pic->i_refcount++;
}
static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
{
video_release_buffer( p_pic );
}
SOURCES_mosaic = mosaic.c SOURCES_mosaic = mosaic.c mosaic.h
SOURCES_transform = transform.c SOURCES_transform = transform.c
SOURCES_invert = invert.c SOURCES_invert = invert.c
SOURCES_adjust = adjust.c SOURCES_adjust = adjust.c
......
...@@ -39,7 +39,9 @@ ...@@ -39,7 +39,9 @@
#include "vlc_filter.h" #include "vlc_filter.h"
#include "vlc_image.h" #include "vlc_image.h"
#include "../video_output/picture.h" #include "mosaic.h"
#define BLANK_DELAY I64C(1000000)
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
...@@ -58,11 +60,9 @@ static int MosaicCallback( vlc_object_t *, char const *, vlc_value_t, ...@@ -58,11 +60,9 @@ static int MosaicCallback( vlc_object_t *, char const *, vlc_value_t,
struct filter_sys_t struct filter_sys_t
{ {
vlc_mutex_t lock; vlc_mutex_t lock;
vlc_mutex_t *p_lock;
image_handler_t *p_image; image_handler_t *p_image;
#ifdef IMAGE_2PASSES
image_handler_t *p_image2;
#endif
picture_t *p_pic; picture_t *p_pic;
int i_position; /* mosaic positioning method */ int i_position; /* mosaic positioning method */
...@@ -108,7 +108,7 @@ struct filter_sys_t ...@@ -108,7 +108,7 @@ struct filter_sys_t
#define DELAY_TEXT N_("Delay") #define DELAY_TEXT N_("Delay")
#define DELAY_LONGTEXT N_("Pictures coming from the picture video outputs " \ #define DELAY_LONGTEXT N_("Pictures coming from the picture video outputs " \
"will be delayed accordingly (in milliseconds, >= 100 ms). For high " \ "will be delayed accordingly (in milliseconds). For high " \
"values you will need to raise file-caching and others.") "values you will need to raise file-caching and others.")
static int pi_pos_values[] = { 0, 1 }; static int pi_pos_values[] = { 0, 1 };
...@@ -145,8 +145,10 @@ vlc_module_begin(); ...@@ -145,8 +145,10 @@ vlc_module_begin();
add_bool( "mosaic-keep-picture", 0, NULL, KEEP_TEXT, KEEP_TEXT, VLC_FALSE ); add_bool( "mosaic-keep-picture", 0, NULL, KEEP_TEXT, KEEP_TEXT, VLC_FALSE );
add_string( "mosaic-order", "", NULL, ORDER_TEXT, ORDER_TEXT, VLC_FALSE ); add_string( "mosaic-order", "", NULL, ORDER_TEXT, ORDER_TEXT, VLC_FALSE );
add_integer( "mosaic-delay", 100, NULL, DELAY_TEXT, DELAY_LONGTEXT, add_integer( "mosaic-delay", 0, NULL, DELAY_TEXT, DELAY_LONGTEXT,
VLC_FALSE ); VLC_FALSE );
var_Create( p_module->p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
vlc_module_end(); vlc_module_end();
...@@ -160,6 +162,7 @@ static int CreateFilter( vlc_object_t *p_this ) ...@@ -160,6 +162,7 @@ static int CreateFilter( vlc_object_t *p_this )
libvlc_t *p_libvlc = p_filter->p_libvlc; libvlc_t *p_libvlc = p_filter->p_libvlc;
char *psz_order; char *psz_order;
int i_index; int i_index;
vlc_value_t val;
/* Allocate structure */ /* Allocate structure */
p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) ); p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
...@@ -175,6 +178,9 @@ static int CreateFilter( vlc_object_t *p_this ) ...@@ -175,6 +178,9 @@ static int CreateFilter( vlc_object_t *p_this )
vlc_mutex_init( p_filter, &p_sys->lock ); vlc_mutex_init( p_filter, &p_sys->lock );
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
var_Get( p_libvlc, "mosaic-lock", &val );
p_sys->p_lock = val.p_address;
#define GET_VAR( name, min, max ) \ #define GET_VAR( name, min, max ) \
p_sys->i_##name = __MIN( max, __MAX( min, \ p_sys->i_##name = __MIN( max, __MAX( min, \
var_CreateGetInteger( p_filter, "mosaic-" #name ) ) ); \ var_CreateGetInteger( p_filter, "mosaic-" #name ) ) ); \
...@@ -216,9 +222,6 @@ static int CreateFilter( vlc_object_t *p_this ) ...@@ -216,9 +222,6 @@ static int CreateFilter( vlc_object_t *p_this )
if ( !p_sys->b_keep ) if ( !p_sys->b_keep )
{ {
p_sys->p_image = image_HandlerCreate( p_filter ); p_sys->p_image = image_HandlerCreate( p_filter );
#ifdef IMAGE_2PASSES
p_sys->p_image2 = image_HandlerCreate( p_filter );
#endif
} }
p_sys->i_order_length = 0; p_sys->i_order_length = 0;
...@@ -244,8 +247,6 @@ static int CreateFilter( vlc_object_t *p_this ) ...@@ -244,8 +247,6 @@ static int CreateFilter( vlc_object_t *p_this )
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
vlc_thread_set_priority( p_filter, VLC_THREAD_PRIORITY_OUTPUT );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -264,9 +265,6 @@ static void DestroyFilter( vlc_object_t *p_this ) ...@@ -264,9 +265,6 @@ static void DestroyFilter( vlc_object_t *p_this )
if( !p_sys->b_keep ) if( !p_sys->b_keep )
{ {
image_HandlerDelete( p_sys->p_image ); image_HandlerDelete( p_sys->p_image );
#ifdef IMAGE_2PASSES
image_HandlerDelete( p_sys->p_image2 );
#endif
} }
if( p_sys->i_order_length ) if( p_sys->i_order_length )
...@@ -313,7 +311,7 @@ static void MosaicReleasePicture( picture_t *p_picture ) ...@@ -313,7 +311,7 @@ static void MosaicReleasePicture( picture_t *p_picture )
static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
{ {
filter_sys_t *p_sys = p_filter->p_sys; filter_sys_t *p_sys = p_filter->p_sys;
libvlc_t *p_libvlc = p_filter->p_libvlc; bridge_t *p_bridge;
subpicture_t *p_spu; subpicture_t *p_spu;
...@@ -323,26 +321,6 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -323,26 +321,6 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
subpicture_region_t *p_region; subpicture_region_t *p_region;
subpicture_region_t *p_region_prev = NULL; subpicture_region_t *p_region_prev = NULL;
picture_vout_t *p_picture_vout;
vlc_value_t val, lockval;
/* Wait for the specified date. This is to avoid running too fast and
* take twice the same pictures. */
mwait( date - p_sys->i_delay );
if ( var_Get( p_libvlc, "picture-lock", &lockval ) )
return NULL;
vlc_mutex_lock( lockval.p_address );
if( var_Get( p_libvlc, "p_picture_vout", &val ) )
{
vlc_mutex_unlock( lockval.p_address );
return NULL;
}
p_picture_vout = val.p_address;
/* Allocate the subpicture internal data. */ /* Allocate the subpicture internal data. */
p_spu = p_filter->pf_sub_buffer_new( p_filter ); p_spu = p_filter->pf_sub_buffer_new( p_filter );
if( !p_spu ) if( !p_spu )
...@@ -360,28 +338,33 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -360,28 +338,33 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
p_spu->b_absolute = VLC_FALSE; p_spu->b_absolute = VLC_FALSE;
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
vlc_mutex_lock( p_sys->p_lock );
p_bridge = GetBridge( p_filter );
if ( p_bridge == NULL )
{
vlc_mutex_unlock( p_sys->p_lock );
vlc_mutex_unlock( &p_sys->lock );
return p_spu;
}
if( p_sys->i_position == 0 ) /* use automatic positioning */ if ( p_sys->i_position == 0 ) /* use automatic positioning */
{ {
int i_numpics = p_sys->i_order_length; /* keep slots and all */ int i_numpics = p_sys->i_order_length; /* keep slots and all */
for( i_index = 0; for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ )
i_index < p_picture_vout->i_picture_num;
i_index++ )
{ {
if( p_picture_vout->p_pic[i_index].i_status bridged_es_t *p_es = p_bridge->pp_es[i_index];
== PICTURE_VOUT_E_OCCUPIED ) if ( !p_es->b_empty )
{ {
i_numpics ++; i_numpics ++;
if( p_sys->i_order_length if( p_sys->i_order_length && p_es->psz_id != 0 )
&& p_picture_vout->p_pic[i_index].psz_id != 0 )
{ {
/* We also want to leave slots for images given in /* We also want to leave slots for images given in
* mosaic-order that are not available in p_vout_picture */ * mosaic-order that are not available in p_vout_picture */
int i; int i;
for( i = 0; i < p_sys->i_order_length ; i++ ) for( i = 0; i < p_sys->i_order_length ; i++ )
{ {
if( !strcmp( p_sys->ppsz_order[i], if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) )
p_picture_vout->p_pic[i_index].psz_id ) )
{ {
i_numpics--; i_numpics--;
break; break;
...@@ -399,50 +382,66 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -399,50 +382,66 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
i_real_index = 0; i_real_index = 0;
for( i_index = 0; i_index < p_picture_vout->i_picture_num; i_index++ ) for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ )
{ {
picture_vout_e_t *p_pic = &p_picture_vout->p_pic[i_index]; bridged_es_t *p_es = p_bridge->pp_es[i_index];
video_format_t fmt_in = {0}, fmt_out = {0}; video_format_t fmt_in = {0}, fmt_out = {0};
picture_t *p_converted; picture_t *p_converted;
#ifdef IMAGE_2PASSES
video_format_t fmt_middle = {0};
picture_t *p_middle;
#endif
if( p_pic->i_status == PICTURE_VOUT_E_AVAILABLE if ( p_es->b_empty || p_es->p_picture == NULL )
|| p_pic->p_picture == NULL ) continue;
if ( p_es->p_picture->date + p_sys->i_delay < date )
{
if ( p_es->p_picture->p_next != NULL )
{
picture_t *p_next = p_es->p_picture->p_next;
p_es->p_picture->pf_release( p_es->p_picture );
p_es->p_picture = p_next;
}
else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY <
date )
{ {
/* Display blank */
p_es->p_picture->pf_release( p_es->p_picture );
p_es->p_picture = NULL;
p_es->pp_last = &p_es->p_picture;
continue; continue;
} }
else
msg_Dbg( p_filter, "too late picture %lld for %s",
date - p_es->p_picture->date - p_sys->i_delay,
p_es->psz_id );
}
if( p_sys->i_order_length == 0 ) if ( p_sys->i_order_length == 0 )
{ {
i_real_index++; i_real_index++;
} }
else else
{ {
int i; int i;
for( i = 0; i <= p_sys->i_order_length; i++ ) for ( i = 0; i <= p_sys->i_order_length; i++ )
{ {
if( i == p_sys->i_order_length ) break; if ( i == p_sys->i_order_length ) break;
if( strcmp( p_pic->psz_id, p_sys->ppsz_order[i] ) == 0 ) if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 )
{ {
i_real_index = i; i_real_index = i;
break; break;
} }
} }
if( i == p_sys->i_order_length ) if ( i == p_sys->i_order_length )
i_real_index = ++i_greatest_real_index_used; i_real_index = ++i_greatest_real_index_used;
} }
i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows; i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows;
i_col = i_real_index % p_sys->i_cols ; i_col = i_real_index % p_sys->i_cols ;
if( !p_sys->b_keep ) if ( !p_sys->b_keep )
{ {
/* Convert the images */ /* Convert the images */
fmt_in.i_chroma = p_pic->p_picture->format.i_chroma; fmt_in.i_chroma = p_es->p_picture->format.i_chroma;
fmt_in.i_height = p_pic->p_picture->format.i_height; fmt_in.i_height = p_es->p_picture->format.i_height;
fmt_in.i_width = p_pic->p_picture->format.i_width; fmt_in.i_width = p_es->p_picture->format.i_width;
fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A'); fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
fmt_out.i_width = fmt_in.i_width * fmt_out.i_width = fmt_in.i_width *
...@@ -457,42 +456,19 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -457,42 +456,19 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
> (float)fmt_in.i_width / (float)fmt_in.i_height ) > (float)fmt_in.i_width / (float)fmt_in.i_height )
{ {
fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width ) fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width )
/ fmt_in.i_height ; / fmt_in.i_height;
} }
else else
{ {
fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height ) fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height )
/ fmt_in.i_width ; / fmt_in.i_width;
} }
} }
fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_width = fmt_out.i_width;
fmt_out.i_visible_height = fmt_out.i_height; fmt_out.i_visible_height = fmt_out.i_height;
#ifdef IMAGE_2PASSES p_converted = image_Convert( p_sys->p_image, p_es->p_picture,
fmt_middle.i_chroma = fmt_in.i_chroma;
fmt_middle.i_visible_width = fmt_middle.i_width = fmt_out.i_width;
fmt_middle.i_visible_height = fmt_middle.i_height = fmt_out.i_height;
p_middle = image_Convert( p_sys->p_image2, p_pic->p_picture,
&fmt_in, &fmt_middle );
if( !p_middle )
{
msg_Warn( p_filter, "image resizing failed" );
continue;
}
p_converted = image_Convert( p_sys->p_image, p_middle,
&fmt_middle, &fmt_out );
p_middle->pf_release( p_middle );
if( !p_converted )
{
msg_Warn( p_filter, "image chroma conversion failed" );
continue;
}
#else
p_converted = image_Convert( p_sys->p_image, p_pic->p_picture,
&fmt_in, &fmt_out ); &fmt_in, &fmt_out );
if( !p_converted ) if( !p_converted )
{ {
...@@ -500,11 +476,10 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -500,11 +476,10 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
"image resizing and chroma conversion failed" ); "image resizing and chroma conversion failed" );
continue; continue;
} }
#endif
} }
else else
{ {
p_converted = p_pic->p_picture; p_converted = p_es->p_picture;
p_converted->i_refcount++; p_converted->i_refcount++;
fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width; fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width;
fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height; fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height;
...@@ -520,8 +495,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -520,8 +495,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
msg_Err( p_filter, "cannot allocate SPU region" ); msg_Err( p_filter, "cannot allocate SPU region" );
p_filter->pf_sub_buffer_del( p_filter, p_spu ); p_filter->pf_sub_buffer_del( p_filter, p_spu );
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( p_sys->p_lock );
return NULL; return p_spu;
} }
/* HACK ALERT : let's fix the pointers to avoid picture duplication. /* HACK ALERT : let's fix the pointers to avoid picture duplication.
...@@ -578,8 +553,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) ...@@ -578,8 +553,8 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
p_region_prev = p_region; p_region_prev = p_region;
} }
vlc_mutex_unlock( p_sys->p_lock );
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
vlc_mutex_unlock( lockval.p_address );
return p_spu; return p_spu;
} }
......
/***************************************************************************** /*****************************************************************************
* picture.h: * mosaic.h:
***************************************************************************** *****************************************************************************
* Copyright (C) 2004-2005 VideoLAN * Copyright (C) 2004-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Antoine Cellerier <dionoea@videolan.org> * Authors: Antoine Cellerier <dionoea@videolan.org>
* Christophe Massiot <massiot@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -21,24 +22,37 @@ ...@@ -21,24 +22,37 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#ifndef _PICTURE_VOUT_H typedef struct bridged_es_t
#define _PICTURE_VOUT_H 1
#define PICTURE_VOUT_E_AVAILABLE 0
#define PICTURE_VOUT_E_OCCUPIED 1
typedef struct picture_vout_e_t
{ {
es_format_t fmt;
picture_t *p_picture; picture_t *p_picture;
int i_status; picture_t **pp_last;
vlc_bool_t b_empty;
char *psz_id; char *psz_id;
} picture_vout_e_t; } bridged_es_t;
typedef struct bridge_t
{
bridged_es_t **pp_es;
int i_es_num;
} bridge_t;
typedef struct picture_vout_t #define GetBridge(a) __GetBridge( VLC_OBJECT(a) )
static bridge_t *__GetBridge( vlc_object_t *p_object )
{ {
int i_picture_num; libvlc_t *p_libvlc = p_object->p_libvlc;
picture_vout_e_t *p_pic; bridge_t *p_bridge;
} picture_vout_t; vlc_value_t val;
if( var_Get( p_libvlc, "mosaic-struct", &val ) != VLC_SUCCESS )
{
p_bridge = NULL;
}
else
{
p_bridge = val.p_address;
}
#undef IMAGE_2PASSES return p_bridge;
}
#endif
...@@ -12,5 +12,3 @@ SOURCES_hd1000v = hd1000v.cpp ...@@ -12,5 +12,3 @@ SOURCES_hd1000v = hd1000v.cpp
SOURCES_snapshot = snapshot.c SOURCES_snapshot = snapshot.c
SOURCES_opengl = opengl.c SOURCES_opengl = opengl.c
SOURCES_image = image.c SOURCES_image = image.c
SOURCES_picture = picture.h \
picture.c
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