1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004-2007 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea@videolan.org>
8 * Christophe Massiot <massiot@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <errno.h> /* ENOMEM */
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
38 #include <vlc_block.h>
39 #include <vlc_codec.h>
41 #include <vlc_image.h>
42 #include <vlc_filter.h>
44 #include "../video_filter/mosaic.h"
48 /*****************************************************************************
50 *****************************************************************************/
51 struct sout_stream_sys_t
57 image_handler_t
*p_image
; /* filter for resizing */
58 int i_height
, i_width
;
59 unsigned int i_sar_num
, i_sar_den
;
63 int i_chroma
; /* force image format chroma */
65 filter_chain_t
*p_vf2
;
68 #define PICTURE_RING_SIZE 4
69 struct decoder_owner_sys_t
71 picture_t
*pp_pics
[PICTURE_RING_SIZE
];
73 /* Current format in use by the output */
77 typedef void (* pf_release_t
)( picture_t
* );
78 static void ReleasePicture( picture_t
*p_pic
)
82 if( --p_pic
->i_refcount
> 0 )
87 pf_release_t pf_release
= (pf_release_t
)p_pic
->p_sys
;
94 free( p_pic
->p_data_orig
);
99 /*****************************************************************************
101 *****************************************************************************/
102 static int Open ( vlc_object_t
* );
103 static void Close ( vlc_object_t
* );
104 static sout_stream_id_t
*Add ( sout_stream_t
*, es_format_t
* );
105 static int Del ( sout_stream_t
*, sout_stream_id_t
* );
106 static int Send( sout_stream_t
*, sout_stream_id_t
*, block_t
* );
108 inline static void video_del_buffer_decoder( decoder_t
*, picture_t
* );
109 inline static void video_del_buffer_filter( filter_t
*, picture_t
* );
110 static void video_del_buffer( picture_t
* );
112 inline static picture_t
*video_new_buffer_decoder( decoder_t
* );
113 inline static picture_t
*video_new_buffer_filter( filter_t
* );
114 static picture_t
*video_new_buffer( vlc_object_t
*, decoder_owner_sys_t
*,
115 es_format_t
*, void (*)( picture_t
* ) );
117 static void video_link_picture_decoder( decoder_t
*, picture_t
* );
118 static void video_unlink_picture_decoder( decoder_t
*, picture_t
* );
120 static int HeightCallback( vlc_object_t
*, char const *,
121 vlc_value_t
, vlc_value_t
, void * );
122 static int WidthCallback( vlc_object_t
*, char const *,
123 vlc_value_t
, vlc_value_t
, void * );
124 static int alphaCallback( vlc_object_t
*, char const *,
125 vlc_value_t
, vlc_value_t
, void * );
126 static int xCallback( vlc_object_t
*, char const *,
127 vlc_value_t
, vlc_value_t
, void * );
128 static int yCallback( vlc_object_t
*, char const *,
129 vlc_value_t
, vlc_value_t
, void * );
131 /*****************************************************************************
133 *****************************************************************************/
134 #define ID_TEXT N_("ID")
135 #define ID_LONGTEXT N_( \
136 "Specify an identifier string for this subpicture" )
138 #define WIDTH_TEXT N_("Video width")
139 #define WIDTH_LONGTEXT N_( \
140 "Output video width." )
141 #define HEIGHT_TEXT N_("Video height")
142 #define HEIGHT_LONGTEXT N_( \
143 "Output video height." )
144 #define RATIO_TEXT N_("Sample aspect ratio")
145 #define RATIO_LONGTEXT N_( \
146 "Sample aspect ratio of the destination (1:1, 3:4, 2:3)." )
148 #define VFILTER_TEXT N_("Video filter")
149 #define VFILTER_LONGTEXT N_( \
150 "Video filters will be applied to the video stream." )
152 #define CHROMA_TEXT N_("Image chroma")
153 #define CHROMA_LONGTEXT N_( \
154 "Force the use of a specific chroma. Use YUVA if you're planning " \
155 "to use the Alphamask or Bluescreen video filter." )
157 #define ALPHA_TEXT N_("Transparency")
158 #define ALPHA_LONGTEXT N_( \
159 "Transparency of the mosaic picture." )
161 #define X_TEXT N_("X offset")
162 #define X_LONGTEXT N_( \
163 "X coordinate of the upper left corner in the mosaic if non negative." )
165 #define Y_TEXT N_("Y offset")
166 #define Y_LONGTEXT N_( \
167 "Y coordinate of the upper left corner in the mosaic if non negative." )
169 #define CFG_PREFIX "sout-mosaic-bridge-"
172 set_shortname( N_( "Mosaic bridge" ) );
173 set_description(N_("Mosaic bridge stream output") );
174 set_capability( "sout stream", 0 );
175 add_shortcut( "mosaic-bridge" );
177 add_string( CFG_PREFIX
"id", "Id", NULL
, ID_TEXT
, ID_LONGTEXT
,
179 add_integer( CFG_PREFIX
"width", 0, NULL
, WIDTH_TEXT
,
180 WIDTH_LONGTEXT
, true );
181 add_integer( CFG_PREFIX
"height", 0, NULL
, HEIGHT_TEXT
,
182 HEIGHT_LONGTEXT
, true );
183 add_string( CFG_PREFIX
"sar", "1:1", NULL
, RATIO_TEXT
,
184 RATIO_LONGTEXT
, false );
185 add_string( CFG_PREFIX
"chroma", 0, NULL
, CHROMA_TEXT
, CHROMA_LONGTEXT
,
188 add_module_list( CFG_PREFIX
"vfilter", "video filter2",
189 NULL
, NULL
, VFILTER_TEXT
, VFILTER_LONGTEXT
, false );
191 add_integer_with_range( CFG_PREFIX
"alpha", 255, 0, 255, NULL
,
192 ALPHA_TEXT
, ALPHA_LONGTEXT
, false );
193 add_integer( CFG_PREFIX
"x", -1, NULL
, X_TEXT
, X_LONGTEXT
, false );
194 add_integer( CFG_PREFIX
"y", -1, NULL
, Y_TEXT
, Y_LONGTEXT
, false );
196 set_callbacks( Open
, Close
);
199 static const char *const ppsz_sout_options
[] = {
200 "id", "width", "height", "sar", "vfilter", "chroma", "alpha", "x", "y", NULL
203 /*****************************************************************************
205 *****************************************************************************/
206 static int Open( vlc_object_t
*p_this
)
208 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
209 sout_stream_sys_t
*p_sys
;
210 vlc_object_t
*p_libvlc
= VLC_OBJECT( p_this
->p_libvlc
);
213 config_ChainParse( p_stream
, CFG_PREFIX
, ppsz_sout_options
,
216 p_sys
= malloc( sizeof( sout_stream_sys_t
) );
220 p_stream
->p_sys
= p_sys
;
221 p_sys
->b_inited
= false;
223 var_Create( p_libvlc
, "mosaic-lock", VLC_VAR_MUTEX
);
224 var_Get( p_libvlc
, "mosaic-lock", &val
);
225 p_sys
->p_lock
= val
.p_address
;
227 p_sys
->psz_id
= var_CreateGetString( p_stream
, CFG_PREFIX
"id" );
230 var_CreateGetIntegerCommand( p_stream
, CFG_PREFIX
"height" );
231 var_AddCallback( p_stream
, CFG_PREFIX
"height", HeightCallback
, p_stream
);
234 var_CreateGetIntegerCommand( p_stream
, CFG_PREFIX
"width" );
235 var_AddCallback( p_stream
, CFG_PREFIX
"width", WidthCallback
, p_stream
);
237 var_Get( p_stream
, CFG_PREFIX
"sar", &val
);
240 char *psz_parser
= strchr( val
.psz_string
, ':' );
244 *psz_parser
++ = '\0';
245 p_sys
->i_sar_num
= atoi( val
.psz_string
);
246 p_sys
->i_sar_den
= atoi( psz_parser
);
247 vlc_ureduce( &p_sys
->i_sar_num
, &p_sys
->i_sar_den
,
248 p_sys
->i_sar_num
, p_sys
->i_sar_den
, 0 );
252 msg_Warn( p_stream
, "bad aspect ratio %s", val
.psz_string
);
253 p_sys
->i_sar_num
= p_sys
->i_sar_den
= 1;
256 free( val
.psz_string
);
260 p_sys
->i_sar_num
= p_sys
->i_sar_den
= 1;
264 val
.psz_string
= var_GetNonEmptyString( p_stream
, CFG_PREFIX
"chroma" );
265 if( val
.psz_string
&& strlen( val
.psz_string
) >= 4 )
267 memcpy( &p_sys
->i_chroma
, val
.psz_string
, 4 );
268 msg_Dbg( p_stream
, "Forcing image chroma to 0x%.8x (%4.4s)", p_sys
->i_chroma
, (char*)&p_sys
->i_chroma
);
270 free( val
.psz_string
);
272 #define INT_COMMAND( a ) do { \
273 var_Create( p_stream, CFG_PREFIX #a, \
274 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND ); \
275 var_AddCallback( p_stream, CFG_PREFIX #a, a ## Callback, \
276 p_stream ); } while(0)
277 INT_COMMAND( alpha
);
283 p_stream
->pf_add
= Add
;
284 p_stream
->pf_del
= Del
;
285 p_stream
->pf_send
= Send
;
287 p_stream
->p_sout
->i_out_pace_nocontrol
++;
292 /*****************************************************************************
294 *****************************************************************************/
295 static void Close( vlc_object_t
* p_this
)
297 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
298 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
300 p_stream
->p_sout
->i_out_pace_nocontrol
--;
302 free( p_sys
->psz_id
);
307 static int video_filter_buffer_allocation_init( filter_t
*p_filter
, void *p_data
)
309 p_filter
->pf_vout_buffer_new
= video_new_buffer_filter
;
310 p_filter
->pf_vout_buffer_del
= video_del_buffer_filter
;
311 p_filter
->p_owner
= p_data
;
315 static sout_stream_id_t
* Add( sout_stream_t
*p_stream
, es_format_t
*p_fmt
)
317 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
323 if( p_sys
->b_inited
|| p_fmt
->i_cat
!= VIDEO_ES
)
326 /* Create decoder object */
327 p_sys
->p_decoder
= vlc_object_create( p_stream
, VLC_OBJECT_DECODER
);
328 if( !p_sys
->p_decoder
)
330 vlc_object_attach( p_sys
->p_decoder
, p_stream
);
331 p_sys
->p_decoder
->p_module
= NULL
;
332 p_sys
->p_decoder
->fmt_in
= *p_fmt
;
333 p_sys
->p_decoder
->b_pace_control
= false;
334 p_sys
->p_decoder
->fmt_out
= p_sys
->p_decoder
->fmt_in
;
335 p_sys
->p_decoder
->fmt_out
.i_extra
= 0;
336 p_sys
->p_decoder
->fmt_out
.p_extra
= 0;
337 p_sys
->p_decoder
->pf_decode_video
= 0;
338 p_sys
->p_decoder
->pf_vout_buffer_new
= video_new_buffer_decoder
;
339 p_sys
->p_decoder
->pf_vout_buffer_del
= video_del_buffer_decoder
;
340 p_sys
->p_decoder
->pf_picture_link
= video_link_picture_decoder
;
341 p_sys
->p_decoder
->pf_picture_unlink
= video_unlink_picture_decoder
;
342 p_sys
->p_decoder
->p_owner
= malloc( sizeof(decoder_owner_sys_t
) );
343 if( !p_sys
->p_decoder
->p_owner
)
345 vlc_object_detach( p_sys
->p_decoder
);
346 vlc_object_release( p_sys
->p_decoder
);
350 for( i
= 0; i
< PICTURE_RING_SIZE
; i
++ )
351 p_sys
->p_decoder
->p_owner
->pp_pics
[i
] = NULL
;
352 p_sys
->p_decoder
->p_owner
->video
= p_fmt
->video
;
353 //p_sys->p_decoder->p_cfg = p_sys->p_video_cfg;
355 p_sys
->p_decoder
->p_module
=
356 module_need( p_sys
->p_decoder
, "decoder", "$codec", 0 );
358 if( !p_sys
->p_decoder
->p_module
|| !p_sys
->p_decoder
->pf_decode_video
)
360 if( p_sys
->p_decoder
->p_module
)
362 msg_Err( p_stream
, "instanciated a non video decoder" );
363 module_unneed( p_sys
->p_decoder
, p_sys
->p_decoder
->p_module
);
367 msg_Err( p_stream
, "cannot find decoder" );
369 free( p_sys
->p_decoder
->p_owner
);
370 vlc_object_detach( p_sys
->p_decoder
);
371 vlc_object_release( p_sys
->p_decoder
);
375 p_sys
->b_inited
= true;
376 vlc_mutex_lock( p_sys
->p_lock
);
378 p_bridge
= GetBridge( p_stream
);
379 if ( p_bridge
== NULL
)
381 vlc_object_t
*p_libvlc
= VLC_OBJECT( p_stream
->p_libvlc
);
384 p_bridge
= malloc( sizeof( bridge_t
) );
386 var_Create( p_libvlc
, "mosaic-struct", VLC_VAR_ADDRESS
);
387 val
.p_address
= p_bridge
;
388 var_Set( p_libvlc
, "mosaic-struct", val
);
390 p_bridge
->i_es_num
= 0;
391 p_bridge
->pp_es
= NULL
;
394 for ( i
= 0; i
< p_bridge
->i_es_num
; i
++ )
396 if ( p_bridge
->pp_es
[i
]->b_empty
)
400 if ( i
== p_bridge
->i_es_num
)
402 p_bridge
->pp_es
= realloc( p_bridge
->pp_es
,
403 (p_bridge
->i_es_num
+ 1)
404 * sizeof(bridged_es_t
*) );
405 p_bridge
->i_es_num
++;
406 p_bridge
->pp_es
[i
] = malloc( sizeof(bridged_es_t
) );
409 p_sys
->p_es
= p_es
= p_bridge
->pp_es
[i
];
411 p_es
->i_alpha
= var_GetInteger( p_stream
, CFG_PREFIX
"alpha" );
412 p_es
->i_x
= var_GetInteger( p_stream
, CFG_PREFIX
"x" );
413 p_es
->i_y
= var_GetInteger( p_stream
, CFG_PREFIX
"y" );
415 //p_es->fmt = *p_fmt;
416 p_es
->psz_id
= p_sys
->psz_id
;
417 p_es
->p_picture
= NULL
;
418 p_es
->pp_last
= &p_es
->p_picture
;
419 p_es
->b_empty
= false;
421 vlc_mutex_unlock( p_sys
->p_lock
);
423 if ( p_sys
->i_height
|| p_sys
->i_width
)
425 p_sys
->p_image
= image_HandlerCreate( p_stream
);
429 p_sys
->p_image
= NULL
;
432 msg_Dbg( p_stream
, "mosaic bridge id=%s pos=%d", p_es
->psz_id
, i
);
434 /* Create user specified video filters */
435 psz_chain
= var_GetNonEmptyString( p_stream
, CFG_PREFIX
"vfilter" );
436 msg_Dbg( p_stream
, "psz_chain: %s\n", psz_chain
);
439 p_sys
->p_vf2
= filter_chain_New( p_stream
, "video filter2", false,
440 video_filter_buffer_allocation_init
,
441 NULL
, p_sys
->p_decoder
->p_owner
);
443 es_format_Copy( &fmt
, &p_sys
->p_decoder
->fmt_out
);
444 if( p_sys
->i_chroma
)
445 fmt
.video
.i_chroma
= p_sys
->i_chroma
;
446 filter_chain_Reset( p_sys
->p_vf2
, &fmt
, &fmt
);
447 filter_chain_AppendFromString( p_sys
->p_vf2
, psz_chain
);
455 return (sout_stream_id_t
*)p_sys
;
458 static int Del( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
461 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
464 bool b_last_es
= true;
467 if( !p_sys
->b_inited
)
470 if( p_sys
->p_decoder
!= NULL
)
472 decoder_owner_sys_t
*p_owner
= p_sys
->p_decoder
->p_owner
;
474 if( p_sys
->p_decoder
->p_module
)
475 module_unneed( p_sys
->p_decoder
, p_sys
->p_decoder
->p_module
);
476 vlc_object_detach( p_sys
->p_decoder
);
477 vlc_object_release( p_sys
->p_decoder
);
479 picture_t
**pp_ring
= p_owner
->pp_pics
;
480 for( i
= 0; i
< PICTURE_RING_SIZE
; i
++ )
482 if ( pp_ring
[i
] != NULL
)
484 free( pp_ring
[i
]->p_data_orig
);
485 free( pp_ring
[i
]->p_sys
);
492 /* Destroy user specified video filters */
494 filter_chain_Delete( p_sys
->p_vf2
);
496 vlc_mutex_lock( p_sys
->p_lock
);
498 p_bridge
= GetBridge( p_stream
);
501 p_es
->b_empty
= true;
502 while ( p_es
->p_picture
)
504 picture_t
*p_next
= p_es
->p_picture
->p_next
;
505 p_es
->p_picture
->pf_release( p_es
->p_picture
);
506 p_es
->p_picture
= p_next
;
509 for ( i
= 0; i
< p_bridge
->i_es_num
; i
++ )
511 if ( !p_bridge
->pp_es
[i
]->b_empty
)
520 vlc_object_t
*p_libvlc
= VLC_OBJECT( p_stream
->p_libvlc
);
521 for ( i
= 0; i
< p_bridge
->i_es_num
; i
++ )
522 free( p_bridge
->pp_es
[i
] );
523 free( p_bridge
->pp_es
);
525 var_Destroy( p_libvlc
, "mosaic-struct" );
528 vlc_mutex_unlock( p_sys
->p_lock
);
530 if ( p_sys
->p_image
)
532 image_HandlerDelete( p_sys
->p_image
);
535 p_sys
->b_inited
= false;
540 /*****************************************************************************
541 * PushPicture : push a picture in the mosaic-struct structure
542 *****************************************************************************/
543 static void PushPicture( sout_stream_t
*p_stream
, picture_t
*p_picture
)
545 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
546 bridged_es_t
*p_es
= p_sys
->p_es
;
548 vlc_mutex_lock( p_sys
->p_lock
);
550 *p_es
->pp_last
= p_picture
;
551 p_picture
->p_next
= NULL
;
552 p_es
->pp_last
= &p_picture
->p_next
;
554 vlc_mutex_unlock( p_sys
->p_lock
);
557 static int Send( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
560 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
563 if ( (sout_stream_sys_t
*)id
!= p_sys
)
565 block_ChainRelease( p_buffer
);
569 while ( (p_pic
= p_sys
->p_decoder
->pf_decode_video( p_sys
->p_decoder
,
572 picture_t
*p_new_pic
;
574 if( p_sys
->i_height
|| p_sys
->i_width
)
576 video_format_t fmt_out
, fmt_in
;
578 memset( &fmt_in
, 0, sizeof(video_format_t
) );
579 memset( &fmt_out
, 0, sizeof(video_format_t
) );
580 fmt_in
= p_sys
->p_decoder
->fmt_out
.video
;
583 if( p_sys
->i_chroma
)
584 fmt_out
.i_chroma
= p_sys
->i_chroma
;
586 fmt_out
.i_chroma
= VLC_FOURCC('I','4','2','0');
588 if ( !p_sys
->i_height
)
590 fmt_out
.i_width
= p_sys
->i_width
;
591 fmt_out
.i_height
= (p_sys
->i_width
* VOUT_ASPECT_FACTOR
592 * p_sys
->i_sar_num
/ p_sys
->i_sar_den
/ fmt_in
.i_aspect
)
595 else if ( !p_sys
->i_width
)
597 fmt_out
.i_height
= p_sys
->i_height
;
598 fmt_out
.i_width
= (p_sys
->i_height
* fmt_in
.i_aspect
599 * p_sys
->i_sar_den
/ p_sys
->i_sar_num
/ VOUT_ASPECT_FACTOR
)
604 fmt_out
.i_width
= p_sys
->i_width
;
605 fmt_out
.i_height
= p_sys
->i_height
;
607 fmt_out
.i_visible_width
= fmt_out
.i_width
;
608 fmt_out
.i_visible_height
= fmt_out
.i_height
;
610 p_new_pic
= image_Convert( p_sys
->p_image
,
611 p_pic
, &fmt_in
, &fmt_out
);
612 if ( p_new_pic
== NULL
)
614 msg_Err( p_stream
, "image conversion failed" );
615 picture_Release( p_pic
);
621 /* TODO: chroma conversion if needed */
623 p_new_pic
= (picture_t
*)malloc( sizeof(picture_t
) );
624 if( p_new_pic
== NULL
)
626 msg_Err( p_stream
, "image conversion failed" );
630 if( vout_AllocatePicture(
631 p_stream
, p_new_pic
, p_pic
->format
.i_chroma
,
632 p_pic
->format
.i_width
, p_pic
->format
.i_height
,
633 p_sys
->p_decoder
->fmt_out
.video
.i_aspect
)
636 picture_Release( p_pic
);
638 msg_Err( p_stream
, "image allocation failed" );
642 picture_Copy( p_new_pic
, p_pic
);
645 p_new_pic
->i_refcount
= 1;
646 p_new_pic
->i_status
= DESTROYED_PICTURE
;
647 p_new_pic
->i_type
= DIRECT_PICTURE
;
648 p_new_pic
->p_sys
= (picture_sys_t
*)p_new_pic
->pf_release
;
649 p_new_pic
->pf_release
= ReleasePicture
;
650 p_new_pic
->date
= p_pic
->date
;
651 picture_Release( p_pic
);
654 p_new_pic
= filter_chain_VideoFilter( p_sys
->p_vf2
, p_new_pic
);
656 PushPicture( p_stream
, p_new_pic
);
664 vlc_object_t
*p_owner
;
668 static void video_release_buffer_decoder( picture_t
*p_pic
)
670 assert( p_pic
&& p_pic
->p_sys
);
672 if( --p_pic
->i_refcount
> 0 )
675 video_del_buffer_decoder( (decoder_t
*)p_pic
->p_sys
->p_owner
, p_pic
);
678 static void video_release_buffer_filter( picture_t
*p_pic
)
682 if( --p_pic
->i_refcount
> 0 )
685 assert( p_pic
->p_sys
);
687 video_del_buffer_filter( (filter_t
*)p_pic
->p_sys
->p_owner
, p_pic
);
690 inline static picture_t
*video_new_buffer_decoder( decoder_t
*p_dec
)
692 return video_new_buffer( VLC_OBJECT( p_dec
),
693 (decoder_owner_sys_t
*)p_dec
->p_owner
,
695 video_release_buffer_decoder
);
698 inline static picture_t
*video_new_buffer_filter( filter_t
*p_filter
)
700 return video_new_buffer( VLC_OBJECT( p_filter
),
701 (decoder_owner_sys_t
*)p_filter
->p_owner
,
703 video_release_buffer_filter
);
706 static picture_t
*video_new_buffer( vlc_object_t
*p_this
,
707 decoder_owner_sys_t
*p_sys
,
708 es_format_t
*fmt_out
,
709 void ( *pf_release
)( picture_t
* ) )
711 picture_t
**pp_ring
= p_sys
->pp_pics
;
715 if( fmt_out
->video
.i_width
!= p_sys
->video
.i_width
||
716 fmt_out
->video
.i_height
!= p_sys
->video
.i_height
||
717 fmt_out
->video
.i_chroma
!= p_sys
->video
.i_chroma
||
718 fmt_out
->video
.i_aspect
!= p_sys
->video
.i_aspect
)
720 if( !fmt_out
->video
.i_sar_num
||
721 !fmt_out
->video
.i_sar_den
)
723 fmt_out
->video
.i_sar_num
=
724 fmt_out
->video
.i_aspect
* fmt_out
->video
.i_height
;
726 fmt_out
->video
.i_sar_den
=
727 VOUT_ASPECT_FACTOR
* fmt_out
->video
.i_width
;
730 vlc_ureduce( &fmt_out
->video
.i_sar_num
,
731 &fmt_out
->video
.i_sar_den
,
732 fmt_out
->video
.i_sar_num
,
733 fmt_out
->video
.i_sar_den
, 0 );
735 if( !fmt_out
->video
.i_visible_width
||
736 !fmt_out
->video
.i_visible_height
)
738 fmt_out
->video
.i_visible_width
= fmt_out
->video
.i_width
;
739 fmt_out
->video
.i_visible_height
= fmt_out
->video
.i_height
;
742 fmt_out
->video
.i_chroma
= fmt_out
->i_codec
;
743 p_sys
->video
= fmt_out
->video
;
745 for( i
= 0; i
< PICTURE_RING_SIZE
; i
++ )
747 if ( pp_ring
[i
] != NULL
)
749 if ( pp_ring
[i
]->i_status
== DESTROYED_PICTURE
)
751 free( pp_ring
[i
]->p_data_orig
);
752 free( pp_ring
[i
]->p_sys
);
757 pp_ring
[i
]->p_sys
->b_dead
= true;
764 /* Find an empty space in the picture ring buffer */
765 for( i
= 0; i
< PICTURE_RING_SIZE
; i
++ )
767 if( pp_ring
[i
] != NULL
&& pp_ring
[i
]->i_status
== DESTROYED_PICTURE
)
769 pp_ring
[i
]->i_status
= RESERVED_PICTURE
;
770 pp_ring
[i
]->i_refcount
= 1;
774 for( i
= 0; i
< PICTURE_RING_SIZE
; i
++ )
776 if( pp_ring
[i
] == NULL
) break;
779 if( i
== PICTURE_RING_SIZE
)
781 msg_Err( p_this
, "decoder/filter is leaking pictures, "
782 "resetting its ring buffer" );
784 for( i
= 0; i
< PICTURE_RING_SIZE
; i
++ )
786 pp_ring
[i
]->p_sys
->b_dead
= true;
787 pp_ring
[i
]->pf_release( pp_ring
[i
] );
794 p_pic
= malloc( sizeof(picture_t
) );
795 if( !p_pic
) return NULL
;
796 fmt_out
->video
.i_chroma
= fmt_out
->i_codec
;
797 if( vout_AllocatePicture( p_this
, p_pic
,
798 fmt_out
->video
.i_chroma
,
799 fmt_out
->video
.i_width
,
800 fmt_out
->video
.i_height
,
801 fmt_out
->video
.i_aspect
) != VLC_SUCCESS
)
807 if( !p_pic
->i_planes
)
813 p_pic
->pf_release
= pf_release
;
814 p_pic
->i_refcount
= 1;
815 p_pic
->p_sys
= malloc( sizeof(picture_sys_t
) );
816 p_pic
->p_sys
->p_owner
= p_this
;
817 p_pic
->p_sys
->b_dead
= false;
818 p_pic
->i_status
= RESERVED_PICTURE
;
825 inline static void video_del_buffer_decoder( decoder_t
*p_this
,
829 video_del_buffer( p_pic
);
832 inline static void video_del_buffer_filter( filter_t
*p_this
,
836 video_del_buffer( p_pic
);
839 static void video_del_buffer( picture_t
*p_pic
)
841 p_pic
->i_refcount
= 0;
842 p_pic
->i_status
= DESTROYED_PICTURE
;
843 if ( p_pic
->p_sys
->b_dead
)
845 free( p_pic
->p_data_orig
);
846 free( p_pic
->p_sys
);
851 static void video_link_picture_decoder( decoder_t
*p_dec
, picture_t
*p_pic
)
857 static void video_unlink_picture_decoder( decoder_t
*p_dec
, picture_t
*p_pic
)
860 video_release_buffer_decoder( p_pic
);
864 /**********************************************************************
865 * Callback to update (some) params on the fly
866 **********************************************************************/
867 static int HeightCallback( vlc_object_t
*p_this
, char const *psz_var
,
868 vlc_value_t oldval
, vlc_value_t newval
,
871 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
872 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
873 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
875 /* We create the handler before updating the value in p_sys
876 * so we don't have to worry about locking */
877 if( !p_sys
->p_image
&& newval
.i_int
)
878 p_sys
->p_image
= image_HandlerCreate( p_stream
);
879 p_sys
->i_height
= newval
.i_int
;
884 static int WidthCallback( vlc_object_t
*p_this
, char const *psz_var
,
885 vlc_value_t oldval
, vlc_value_t newval
,
888 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
889 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
890 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
892 /* We create the handler before updating the value in p_sys
893 * so we don't have to worry about locking */
894 if( !p_sys
->p_image
&& newval
.i_int
)
895 p_sys
->p_image
= image_HandlerCreate( p_stream
);
896 p_sys
->i_width
= newval
.i_int
;
901 static int alphaCallback( vlc_object_t
*p_this
, char const *psz_var
,
902 vlc_value_t oldval
, vlc_value_t newval
,
905 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
906 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
907 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
910 p_sys
->p_es
->i_alpha
= newval
.i_int
;
915 static int xCallback( vlc_object_t
*p_this
, char const *psz_var
,
916 vlc_value_t oldval
, vlc_value_t newval
,
919 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
920 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
921 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
924 p_sys
->p_es
->i_x
= newval
.i_int
;
929 static int yCallback( vlc_object_t
*p_this
, char const *psz_var
,
930 vlc_value_t oldval
, vlc_value_t newval
,
933 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
934 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
935 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
938 p_sys
->p_es
->i_y
= newval
.i_int
;