module "mosaic-bridge".
VLC_ADD_PLUGINS([externrun])
VLC_ADD_PLUGINS([access_fake access_filter_timeshift])
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([aout_file linear_resampler bandlimited_resampler])
VLC_ADD_PLUGINS([float32_mixer spdif_mixer simple_channel_mixer])
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_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])
AC_DEFINE(ENABLE_SOUT, 1, Define if you want the stream output support)
if test "${enable_speex}" != "no"
then
AC_CHECK_HEADERS(speex/speex.h, [
- LDFLAGS="${LDFLAGS_save} ${LDFLAGS_toolame}"
+ LDFLAGS="${LDFLAGS_save} ${LDFLAGS_speex}"
AC_CHECK_LIB(speex, speex_decode_int, [
VLC_ADD_PLUGINS([speex])
VLC_ADD_LDFLAGS([speex],[-lspeex]) ],
SOURCES_stream_out_rtp = rtp.c
SOURCES_stream_out_switcher = switcher.c
SOURCES_stream_out_bridge = bridge.c
+SOURCES_stream_out_mosaic_bridge = mosaic_bridge.c
set_shortname( _("Bridge"));
set_description( _("Bridge stream output"));
add_submodule();
- set_section( N_("Bridge out"),NULL);
+ set_section( N_("Bridge out"), NULL );
set_capability( "sout stream", 50 );
add_shortcut( "bridge-out" );
/* Only usable with VLM. No category so not in gui preferences
set_callbacks( OpenOut, CloseOut );
add_submodule();
- set_section( N_("Bridge in"),NULL);
+ set_section( N_("Bridge in"), NULL );
set_capability( "sout stream", 50 );
add_shortcut( "bridge-in" );
/*set_category( CAT_SOUT );
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 );
add_integer( SOUT_CFG_PREFIX_IN "id-offset", 8192, NULL, ID_OFFSET_TEXT,
ID_OFFSET_LONGTEXT, VLC_FALSE );
block_t *p_block;
block_t **pp_last;
vlc_bool_t b_empty;
- int i_id;
/* bridge in part */
sout_stream_id_t *id;
typedef struct out_sout_stream_sys_t
{
vlc_mutex_t *p_lock;
+ bridged_es_t *p_es;
int i_id;
vlc_bool_t b_inited;
- int i_position;
} out_sout_stream_sys_t;
/*****************************************************************************
*****************************************************************************/
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;
vlc_value_t val;
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++;
return VLC_SUCCESS;
p_bridge->pp_es = realloc( p_bridge->pp_es,
(p_bridge->i_es_num + 1)
* sizeof(bridged_es_t *) );
- p_sys->i_position = p_bridge->i_es_num;
p_bridge->i_es_num++;
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.i_id = p_sys->i_id;
p_es->p_block = NULL;
p_es->b_changed = VLC_TRUE;
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 );
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;
- bridge_t *p_bridge;
bridged_es_t *p_es;
if ( !p_sys->b_inited )
vlc_mutex_lock( p_sys->p_lock );
- p_bridge = GetBridge( p_stream );
- p_es = p_bridge->pp_es[ p_sys->i_position ];
+ p_es = p_sys->p_es;
p_es->b_empty = VLC_TRUE;
block_ChainRelease( p_es->p_block );
block_t *p_buffer )
{
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;
if ( (out_sout_stream_sys_t *)id != p_sys )
vlc_mutex_lock( p_sys->p_lock );
- p_bridge = GetBridge( p_stream );
- p_es = p_bridge->pp_es[ p_sys->i_position ];
+ p_es = p_sys->p_es;
*p_es->pp_last = p_buffer;
while ( p_buffer != NULL )
{
--- /dev/null
+/*****************************************************************************
+ * mosaic_bridge.c:
+ *****************************************************************************
+ * Copyright (C) 2004-2005 VideoLAN
+ * $Id$
+ *
+ * Authors: Antoine Cellerier <dionoea@videolan.org>
+ * Christophe Massiot <massiot@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h> /* ENOMEM */
+#include <stdlib.h> /* free() */
+#include <string.h> /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/sout.h>
+#include <vlc/decoder.h>
+
+#include "vlc_image.h"
+
+#include "../video_filter/mosaic.h"
+
+/*****************************************************************************
+ * Local structures
+ *****************************************************************************/
+struct sout_stream_sys_t
+{
+ bridged_es_t *p_es;
+ vlc_mutex_t *p_lock;
+
+ decoder_t *p_decoder;
+ image_handler_t *p_image; /* filter for resizing */
+ int i_height, i_width;
+ char *psz_id;
+ vlc_bool_t b_inited;
+};
+
+#define PICTURE_RING_SIZE 64
+struct decoder_owner_sys_t
+{
+ picture_t *pp_pics[PICTURE_RING_SIZE];
+};
+
+typedef void (* pf_release_t)( picture_t * );
+static void ReleasePicture( picture_t *p_pic )
+{
+ p_pic->i_refcount--;
+
+ if ( p_pic->i_refcount <= 0 )
+ {
+ if ( p_pic->p_sys != NULL )
+ {
+ pf_release_t pf_release = (pf_release_t)p_pic->p_sys;
+ p_pic->p_sys = NULL;
+ pf_release( p_pic );
+ }
+ else
+ {
+ if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
+ if( p_pic ) free( p_pic );
+ }
+ }
+}
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
+static int Del ( sout_stream_t *, sout_stream_id_t * );
+static int Send( sout_stream_t *, sout_stream_id_t *, block_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
+ *****************************************************************************/
+#define ID_TEXT N_("ID")
+#define ID_LONGTEXT N_( \
+ "Specify an identifier string for this subpicture" )
+
+#define WIDTH_TEXT N_("Video width")
+#define WIDTH_LONGTEXT N_( \
+ "Allows you to specify the output video width." )
+#define HEIGHT_TEXT N_("Video height")
+#define HEIGHT_LONGTEXT N_( \
+ "Allows you to specify the output video height." )
+
+#define SOUT_CFG_PREFIX "sout-mosaic-bridge-"
+
+vlc_module_begin();
+ 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 );
+ add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
+ HEIGHT_LONGTEXT, VLC_TRUE );
+
+ set_callbacks( Open, Close );
+
+ var_Create( p_module->p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
+vlc_module_end();
+
+static const char *ppsz_sout_options[] = {
+ "id", "width", "height", NULL
+};
+
+/*****************************************************************************
+ * Open
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t *)p_this;
+ sout_stream_sys_t *p_sys;
+ libvlc_t *p_libvlc = p_this->p_libvlc;
+ vlc_value_t val;
+
+ sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
+ p_stream->p_cfg );
+
+ p_sys = malloc( sizeof( sout_stream_sys_t ) );
+ p_stream->p_sys = p_sys;
+ p_sys->b_inited = VLC_FALSE;
+
+ var_Get( p_libvlc, "mosaic-lock", &val );
+ p_sys->p_lock = val.p_address;
+
+ var_Get( p_stream, SOUT_CFG_PREFIX "id", &val );
+ p_sys->psz_id = val.psz_string;
+
+ var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
+ p_sys->i_height = val.i_int;
+
+ var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
+ p_sys->i_width = val.i_int;
+
+ if ( p_sys->i_height || p_sys->i_width )
+ {
+ p_sys->p_image = image_HandlerCreate( p_stream );
+ }
+
+ p_stream->pf_add = Add;
+ p_stream->pf_del = Del;
+ p_stream->pf_send = Send;
+
+ p_stream->p_sout->i_out_pace_nocontrol++;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close
+ *****************************************************************************/
+static void Close( vlc_object_t * p_this )
+{
+ sout_stream_t *p_stream = (sout_stream_t*)p_this;
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+
+ p_stream->p_sout->i_out_pace_nocontrol--;
+
+ if ( p_sys->psz_id )
+ free( p_sys->psz_id );
+
+ free( p_sys );
+}
+
+static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
+{
+ 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 )
+ {
+ return 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 )
+ {
+ msg_Err( p_stream, "cannot find decoder" );
+ vlc_object_detach( p_sys->p_decoder );
+ vlc_object_destroy( p_sys->p_decoder );
+ return NULL;
+ }
+
+ p_sys->b_inited = VLC_TRUE;
+ vlc_mutex_lock( p_sys->p_lock );
+
+ p_bridge = GetBridge( p_stream );
+ if ( p_bridge == NULL )
+ {
+ libvlc_t *p_libvlc = p_stream->p_libvlc;
+ vlc_value_t val;
+
+ p_bridge = malloc( sizeof( bridge_t ) );
+
+ var_Create( p_libvlc, "mosaic-struct", VLC_VAR_ADDRESS );
+ val.p_address = p_bridge;
+ var_Set( p_libvlc, "mosaic-struct", val );
+
+ p_bridge->i_es_num = 0;
+ p_bridge->pp_es = NULL;
+ }
+
+ 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];
+
+ //p_es->fmt = *p_fmt;
+ p_es->psz_id = p_sys->psz_id;
+ p_es->p_picture = NULL;
+ 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 )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ bridge_t *p_bridge;
+ bridged_es_t *p_es;
+ vlc_bool_t b_last_es = VLC_TRUE;
+ 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 );
+
+ p_bridge = GetBridge( p_stream );
+ p_es = p_sys->p_es;
+
+ p_es->b_empty = VLC_TRUE;
+ while ( p_es->p_picture )
+ {
+ 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;
+ }
+
+ for ( i = 0; i < p_bridge->i_es_num; i++ )
+ {
+ if ( !p_bridge->pp_es[i]->b_empty )
+ {
+ b_last_es = VLC_FALSE;
+ break;
+ }
+ }
+
+ if ( b_last_es )
+ {
+ libvlc_t *p_libvlc = p_stream->p_libvlc;
+ for ( i = 0; i < p_bridge->i_es_num; i++ )
+ 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 );
+
+ if ( p_sys->i_height || p_sys->i_width )
+ {
+ image_HandlerDelete( p_sys->p_image );
+ }
+
+ p_sys->b_inited = VLC_FALSE;
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * PushPicture : push a picture in the mosaic-struct structure
+ *****************************************************************************/
+static void PushPicture( sout_stream_t *p_stream, picture_t *p_picture )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ bridged_es_t *p_es = p_sys->p_es;
+
+ vlc_mutex_lock( p_sys->p_lock );
+
+ *p_es->pp_last = p_picture;
+ p_picture->p_next = NULL;
+ p_es->pp_last = &p_picture->p_next;
+
+ vlc_mutex_unlock( p_sys->p_lock );
+}
+
+static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
+ block_t *p_buffer )
+{
+ sout_stream_sys_t *p_sys = p_stream->p_sys;
+ picture_t *p_pic;
+
+ if ( (sout_stream_sys_t *)id != p_sys )
+ {
+ block_ChainRelease( p_buffer );
+ return VLC_SUCCESS;
+ }
+
+ while ( (p_pic = p_sys->p_decoder->pf_decode_video( p_sys->p_decoder,
+ &p_buffer )) )
+ {
+ picture_t *p_new_pic;
+
+ if ( p_sys->i_height || p_sys->i_width )
+ {
+ video_format_t fmt_out = {0}, fmt_in = {0};
+ fmt_in = p_sys->p_decoder->fmt_out.video;
+
+ fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
+ fmt_out.i_width = p_sys->i_width;
+ fmt_out.i_height = p_sys->i_height;
+ fmt_out.i_visible_width = fmt_out.i_width;
+ fmt_out.i_visible_height = fmt_out.i_height;
+
+ p_new_pic = image_Convert( p_sys->p_image,
+ p_pic, &fmt_in, &fmt_out );
+ if ( p_new_pic == NULL )
+ {
+ msg_Err( p_stream, "image conversion failed" );
+ continue;
+ }
+ }
+ else
+ {
+ p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
+ vout_AllocatePicture( p_stream, p_new_pic, p_pic->format.i_chroma,
+ p_pic->format.i_width, p_pic->format.i_height,
+ p_sys->p_decoder->fmt_out.video.i_aspect );
+
+ 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_status = DESTROYED_PICTURE;
+ p_new_pic->i_type = DIRECT_PICTURE;
+ p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release;
+ p_new_pic->pf_release = ReleasePicture;
+ p_new_pic->date = p_pic->date;
+
+ PushPicture( p_stream, p_new_pic );
+ }
+
+ return VLC_SUCCESS;
+}
+
+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_invert = invert.c
SOURCES_adjust = adjust.c
#include "vlc_filter.h"
#include "vlc_image.h"
-#include "../video_output/picture.h"
+#include "mosaic.h"
+
+#define BLANK_DELAY I64C(1000000)
/*****************************************************************************
* Local prototypes
struct filter_sys_t
{
vlc_mutex_t lock;
+ vlc_mutex_t *p_lock;
image_handler_t *p_image;
-#ifdef IMAGE_2PASSES
- image_handler_t *p_image2;
-#endif
picture_t *p_pic;
int i_position; /* mosaic positioning method */
#define DELAY_TEXT N_("Delay")
#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.")
static int pi_pos_values[] = { 0, 1 };
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_integer( "mosaic-delay", 100, NULL, DELAY_TEXT, DELAY_LONGTEXT,
+ add_integer( "mosaic-delay", 0, NULL, DELAY_TEXT, DELAY_LONGTEXT,
VLC_FALSE );
+
+ var_Create( p_module->p_libvlc, "mosaic-lock", VLC_VAR_MUTEX );
vlc_module_end();
libvlc_t *p_libvlc = p_filter->p_libvlc;
char *psz_order;
int i_index;
+ vlc_value_t val;
/* Allocate structure */
p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
vlc_mutex_init( p_filter, &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 ) \
p_sys->i_##name = __MIN( max, __MAX( min, \
var_CreateGetInteger( p_filter, "mosaic-" #name ) ) ); \
if ( !p_sys->b_keep )
{
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;
vlc_mutex_unlock( &p_sys->lock );
- vlc_thread_set_priority( p_filter, VLC_THREAD_PRIORITY_OUTPUT );
-
return VLC_SUCCESS;
}
if( !p_sys->b_keep )
{
image_HandlerDelete( p_sys->p_image );
-#ifdef IMAGE_2PASSES
- image_HandlerDelete( p_sys->p_image2 );
-#endif
}
if( p_sys->i_order_length )
static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
{
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_region_t *p_region;
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. */
p_spu = p_filter->pf_sub_buffer_new( p_filter );
if( !p_spu )
p_spu->b_absolute = VLC_FALSE;
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 */
- 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++ )
{
- if( p_picture_vout->p_pic[i_index].i_status
- == PICTURE_VOUT_E_OCCUPIED )
+ bridged_es_t *p_es = p_bridge->pp_es[i_index];
+ if ( !p_es->b_empty )
{
i_numpics ++;
- if( p_sys->i_order_length
- && p_picture_vout->p_pic[i_index].psz_id != 0 )
+ if( p_sys->i_order_length && p_es->psz_id != 0 )
{
/* We also want to leave slots for images given in
* mosaic-order that are not available in p_vout_picture */
int i;
for( i = 0; i < p_sys->i_order_length ; i++ )
{
- if( !strcmp( p_sys->ppsz_order[i],
- p_picture_vout->p_pic[i_index].psz_id ) )
+ if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) )
{
i_numpics--;
break;
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};
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
- || p_pic->p_picture == NULL )
- {
+ if ( p_es->b_empty || p_es->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;
+ }
+ 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++;
}
else
{
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( strcmp( p_pic->psz_id, p_sys->ppsz_order[i] ) == 0 )
+ if ( i == p_sys->i_order_length ) break;
+ if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 )
{
i_real_index = i;
break;
}
}
- if( i == p_sys->i_order_length )
+ if ( i == p_sys->i_order_length )
i_real_index = ++i_greatest_real_index_used;
}
i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows;
i_col = i_real_index % p_sys->i_cols ;
- if( !p_sys->b_keep )
+ if ( !p_sys->b_keep )
{
/* Convert the images */
- fmt_in.i_chroma = p_pic->p_picture->format.i_chroma;
- fmt_in.i_height = p_pic->p_picture->format.i_height;
- fmt_in.i_width = p_pic->p_picture->format.i_width;
+ fmt_in.i_chroma = p_es->p_picture->format.i_chroma;
+ fmt_in.i_height = p_es->p_picture->format.i_height;
+ fmt_in.i_width = p_es->p_picture->format.i_width;
fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
fmt_out.i_width = fmt_in.i_width *
> (float)fmt_in.i_width / (float)fmt_in.i_height )
{
fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width )
- / fmt_in.i_height ;
+ / fmt_in.i_height;
}
else
{
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_height = fmt_out.i_height;
-#ifdef IMAGE_2PASSES
- 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,
+ p_converted = image_Convert( p_sys->p_image, p_es->p_picture,
&fmt_in, &fmt_out );
if( !p_converted )
{
"image resizing and chroma conversion failed" );
continue;
}
-#endif
}
else
{
- p_converted = p_pic->p_picture;
+ p_converted = p_es->p_picture;
p_converted->i_refcount++;
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;
msg_Err( p_filter, "cannot allocate SPU region" );
p_filter->pf_sub_buffer_del( p_filter, p_spu );
vlc_mutex_unlock( &p_sys->lock );
- vlc_mutex_unlock( lockval.p_address );
- return NULL;
+ vlc_mutex_unlock( p_sys->p_lock );
+ return p_spu;
}
/* HACK ALERT : let's fix the pointers to avoid picture duplication.
p_region_prev = p_region;
}
+ vlc_mutex_unlock( p_sys->p_lock );
vlc_mutex_unlock( &p_sys->lock );
- vlc_mutex_unlock( lockval.p_address );
return p_spu;
}
/*****************************************************************************
- * picture.h:
+ * mosaic.h:
*****************************************************************************
* Copyright (C) 2004-2005 VideoLAN
* $Id$
*
* Authors: Antoine Cellerier <dionoea@videolan.org>
+ * Christophe Massiot <massiot@via.ecp.fr>
*
* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-#ifndef _PICTURE_VOUT_H
-#define _PICTURE_VOUT_H 1
-
-#define PICTURE_VOUT_E_AVAILABLE 0
-#define PICTURE_VOUT_E_OCCUPIED 1
-typedef struct picture_vout_e_t
+typedef struct bridged_es_t
{
+ es_format_t fmt;
picture_t *p_picture;
- int i_status;
+ picture_t **pp_last;
+ vlc_bool_t b_empty;
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;
- picture_vout_e_t *p_pic;
-} picture_vout_t;
+ libvlc_t *p_libvlc = p_object->p_libvlc;
+ bridge_t *p_bridge;
+ 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
SOURCES_snapshot = snapshot.c
SOURCES_opengl = opengl.c
SOURCES_image = image.c
-SOURCES_picture = picture.h \
- picture.c
+++ /dev/null
-/*****************************************************************************
- * picture.c:
- *****************************************************************************
- * Copyright (C) 2004-2005 VideoLAN
- * $Id$
- *
- * Authors: Antoine Cellerier <dionoea@videolan.org>
- * Christophe Massiot <massiot@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <errno.h> /* ENOMEM */
-#include <stdlib.h> /* free() */
-#include <string.h> /* strerror() */
-
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-
-#include "vlc_image.h"
-
-#include "picture.h"
-
-/*****************************************************************************
- * Local structures
- *****************************************************************************/
-struct vout_sys_t
-{
- picture_vout_t *p_picture_vout;
- vlc_mutex_t *p_lock;
-
- int i_picture_pos; /* picture position in p_picture_vout */
- image_handler_t *p_image; /* filters for resizing */
-#ifdef IMAGE_2PASSES
- image_handler_t *p_image2;
-#endif
- int i_height, i_width;
- mtime_t i_last_pic;
-};
-
-/* Delay after which the picture is blanked out if there hasn't been any
- * new picture. */
-#define BLANK_DELAY I64C(1000000)
-
-typedef void (* pf_release_t)( picture_t * );
-static void ReleasePicture( picture_t *p_pic )
-{
- p_pic->i_refcount--;
-
- if ( p_pic->i_refcount <= 0 )
- {
- if ( p_pic->p_sys != NULL )
- {
- pf_release_t pf_release = (pf_release_t)p_pic->p_sys;
- p_pic->p_sys = NULL;
- pf_release( p_pic );
- }
- else
- {
- if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
- if( p_pic ) free( p_pic );
- }
- }
-}
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-static int Open ( vlc_object_t * );
-static void Close ( vlc_object_t * );
-static int Init ( vout_thread_t * );
-static void End ( vout_thread_t * );
-static int Manage ( vout_thread_t * );
-static void Display ( vout_thread_t *, picture_t * );
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-#define ID_TEXT N_("ID")
-#define ID_LONGTEXT N_( \
- "Specify an identifier string for this subpicture" )
-
-#define WIDTH_TEXT N_("Video width")
-#define WIDTH_LONGTEXT N_( \
- "Allows you to specify the output video width." )
-#define HEIGHT_TEXT N_("Video height")
-#define HEIGHT_LONGTEXT N_( \
- "Allows you to specify the output video height." )
-
-vlc_module_begin();
- 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 );
- add_integer( "picture-width", 0, NULL, WIDTH_TEXT,
- WIDTH_LONGTEXT, VLC_TRUE );
- add_integer( "picture-height", 0, NULL, HEIGHT_TEXT,
- HEIGHT_LONGTEXT, VLC_TRUE );
-
- set_callbacks( Open, Close );
-
- var_Create( p_module->p_libvlc, "picture-lock", VLC_VAR_MUTEX );
-vlc_module_end();
-
-/*****************************************************************************
- * Open : allocate video thread output method
- *****************************************************************************/
-static int Open( vlc_object_t *p_this )
-{
- vout_thread_t *p_vout = (vout_thread_t *)p_this;
- vout_sys_t *p_sys;
- libvlc_t *p_libvlc = p_vout->p_libvlc;
- picture_vout_t *p_picture_vout = NULL;
- 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 )
- p_sys->i_picture_pos = i;
- }
-
- p_sys->p_picture_vout = p_picture_vout;
-
- if ( p_sys->i_picture_pos == -1 )
- {
- 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];
- p_pic->p_picture = NULL;
- p_pic->i_status = PICTURE_VOUT_E_OCCUPIED;
-
- var_Create( p_vout, "picture-id", VLC_VAR_STRING );
- 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;
-
- var_Create( p_vout, "picture-width", VLC_VAR_INTEGER );
- var_Change( p_vout, "picture-width", VLC_VAR_INHERITVALUE, &val, NULL );
- p_sys->i_width = val.i_int;
-
- if ( p_sys->i_height || p_sys->i_width )
- {
- p_sys->p_image = image_HandlerCreate( p_vout );
-#ifdef IMAGE_2PASSES
- p_sys->p_image2 = image_HandlerCreate( p_vout );
-#endif
- }
-
- p_sys->i_last_pic = 0;
-
- p_vout->pf_init = Init;
- p_vout->pf_end = End;
- p_vout->pf_manage = Manage;
- p_vout->pf_render = NULL;
- p_vout->pf_display = Display;
-
- return VLC_SUCCESS;
-}
-
-
-/*****************************************************************************
- * Init
- *****************************************************************************/
-static int Init( vout_thread_t *p_vout )
-{
- picture_t *p_pic;
- int i_index;
-
- I_OUTPUTPICTURES = 0;
-
- p_vout->output.i_chroma = p_vout->render.i_chroma;
- p_vout->output.i_width = p_vout->render.i_width;
- p_vout->output.i_height = p_vout->render.i_height;
- p_vout->output.i_aspect = p_vout->render.i_aspect;
-
- while( VLC_TRUE )
- {
- p_pic = NULL;
-
- for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
- {
- if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
- {
- p_pic = p_vout->p_picture + i_index;
- break;
- }
- }
-
- if( p_pic == NULL )
- {
- return VLC_SUCCESS;
- }
-
- vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic,
- p_vout->output.i_chroma,
- p_vout->output.i_width, p_vout->output.i_height,
- p_vout->output.i_aspect );
-
- if( p_pic->i_planes == 0 )
- {
- return VLC_EGENERIC;
- }
-
- p_pic->i_status = DESTROYED_PICTURE;
- p_pic->i_type = DIRECT_PICTURE;
-
- PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
-
- I_OUTPUTPICTURES++;
-
- //return VLC_SUCCESS;
- }
-
-}
-
-/*****************************************************************************
- * End
- *****************************************************************************/
-static void End( vout_thread_t *p_vout )
-{
- return;
-}
-
-/*****************************************************************************
- * Close
- *****************************************************************************/
-static void Close( vlc_object_t *p_this )
-{
- vout_thread_t *p_vout = (vout_thread_t *)p_this;
- vout_sys_t *p_sys = p_vout->p_sys;
- picture_vout_t *p_picture_vout = p_sys->p_picture_vout;
- picture_vout_e_t *p_pic;
- vlc_bool_t b_last_picture = VLC_TRUE;
- int i;
-
- 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_pic->p_picture->pf_release( p_pic->p_picture );
- p_pic->p_picture = NULL;
- }
- 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 ++)
- {
- if( p_picture_vout->p_pic[i].i_status == PICTURE_VOUT_E_OCCUPIED )
- {
- b_last_picture = VLC_FALSE;
- break;
- }
- }
-
- if( b_last_picture )
- {
- free( p_picture_vout->p_pic );
- free( p_picture_vout );
- var_Destroy( p_this->p_libvlc, "p_picture_vout" );
- }
-
- vlc_mutex_unlock( p_sys->p_lock );
-
- if ( p_sys->i_height || p_sys->i_width )
- {
- image_HandlerDelete( p_sys->p_image );
-#ifdef IMAGE_2PASSES
- image_HandlerDelete( p_sys->p_image2 );
-#endif
- }
-
- free( p_sys );
-}
-
-/*****************************************************************************
- * PushPicture : push a picture in the p_picture_vout structure
- *****************************************************************************/
-static void PushPicture( vout_thread_t *p_vout, picture_t *p_picture )
-{
- vout_sys_t *p_sys = p_vout->p_sys;
- picture_vout_t *p_picture_vout = p_sys->p_picture_vout;
- picture_vout_e_t *p_pic;
-
- 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_pic->p_picture->pf_release( p_pic->p_picture );
- }
- p_pic->p_picture = p_picture;
-
- vlc_mutex_unlock( p_sys->p_lock );
-}
-
-/*****************************************************************************
- * Manage
- *****************************************************************************/
-static int Manage( vout_thread_t *p_vout )
-{
- vout_sys_t *p_sys = p_vout->p_sys;
-
- 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 )
- {
- 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,
- p_vout->render.i_width,
- p_vout->render.i_height,
- p_vout->render.i_aspect );
- }
-
- p_new_pic->i_refcount++;
- p_new_pic->i_status = DESTROYED_PICTURE;
- 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;
-
- if ( p_sys->i_height || p_sys->i_width )
- {
- video_format_t fmt_out = {0}, fmt_in = {0};
-#ifdef IMAGE_2PASSES
- 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_width = p_sys->i_width;
- fmt_out.i_height = p_sys->i_height;
- fmt_out.i_visible_width = fmt_out.i_width;
- fmt_out.i_visible_height = fmt_out.i_height;
-
-#ifdef IMAGE_2PASSES
- 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 );
-#endif
- if ( p_new_pic == NULL )
- {
- msg_Err( p_vout, "image conversion failed" );
- return;
- }
- }
- else
- {
- p_new_pic = (picture_t*)malloc( sizeof(picture_t) );
- vout_AllocatePicture( p_vout, p_new_pic, p_pic->format.i_chroma,
- p_pic->format.i_width, p_pic->format.i_height,
- p_vout->render.i_aspect );
-
- vout_CopyPicture( p_vout, p_new_pic, p_pic );
- }
-
- p_new_pic->i_refcount = 1;
- p_new_pic->i_status = DESTROYED_PICTURE;
- p_new_pic->i_type = DIRECT_PICTURE;
- p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release;
- p_new_pic->pf_release = ReleasePicture;
-
- PushPicture( p_vout, p_new_pic );
- p_sys->i_last_pic = p_pic->date;
-}