1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004-2007 VLC authors and VideoLAN
6 * Authors: Antoine Cellerier <dionoea@videolan.org>
7 * Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
35 #include <vlc_block.h>
36 #include <vlc_codec.h>
39 #include <vlc_image.h>
40 #include <vlc_filter.h>
41 #include <vlc_modules.h>
43 #include "../spu/mosaic.h"
45 /*****************************************************************************
47 *****************************************************************************/
53 image_handler_t
*p_image
; /* filter for resizing */
54 int i_height
, i_width
;
55 unsigned int i_sar_num
, i_sar_den
;
59 vlc_fourcc_t i_chroma
; /* force image format chroma */
61 filter_chain_t
*p_vf2
;
67 vlc_decoder_device
*dec_dev
;
68 sout_stream_t
*p_stream
;
71 static inline struct decoder_owner
*dec_get_owner( decoder_t
*p_dec
)
73 return container_of( p_dec
, struct decoder_owner
, dec
);
76 /*****************************************************************************
78 *****************************************************************************/
79 static int Open ( vlc_object_t
* );
80 static void Close ( vlc_object_t
* );
81 static void *Add( sout_stream_t
*, const es_format_t
* );
82 static void Del( sout_stream_t
*, void * );
83 static int Send( sout_stream_t
*, void *, block_t
* );
85 static void decoder_queue_video( decoder_t
*p_dec
, picture_t
*p_pic
);
86 static int video_update_format_decoder( decoder_t
*p_dec
, vlc_video_context
* );
87 static picture_t
*video_new_buffer_filter( filter_t
* );
89 static int HeightCallback( vlc_object_t
*, char const *,
90 vlc_value_t
, vlc_value_t
, void * );
91 static int WidthCallback( vlc_object_t
*, char const *,
92 vlc_value_t
, vlc_value_t
, void * );
93 static int alphaCallback( vlc_object_t
*, char const *,
94 vlc_value_t
, vlc_value_t
, void * );
95 static int xCallback( vlc_object_t
*, char const *,
96 vlc_value_t
, vlc_value_t
, void * );
97 static int yCallback( vlc_object_t
*, char const *,
98 vlc_value_t
, vlc_value_t
, void * );
100 /*****************************************************************************
102 *****************************************************************************/
103 #define ID_TEXT N_("ID")
104 #define ID_LONGTEXT N_( \
105 "Specify an identifier string for this subpicture" )
107 #define WIDTH_TEXT N_("Video width")
108 #define WIDTH_LONGTEXT N_( \
109 "Output video width." )
110 #define HEIGHT_TEXT N_("Video height")
111 #define HEIGHT_LONGTEXT N_( \
112 "Output video height." )
113 #define RATIO_TEXT N_("Sample aspect ratio")
114 #define RATIO_LONGTEXT N_( \
115 "Sample aspect ratio of the destination (1:1, 3:4, 2:3)." )
117 #define VFILTER_TEXT N_("Video filter")
118 #define VFILTER_LONGTEXT N_( \
119 "Video filters will be applied to the video stream." )
121 #define CHROMA_TEXT N_("Image chroma")
122 #define CHROMA_LONGTEXT N_( \
123 "Force the use of a specific chroma. Use YUVA if you're planning " \
124 "to use the Alphamask or Bluescreen video filter." )
126 #define ALPHA_TEXT N_("Transparency")
127 #define ALPHA_LONGTEXT N_( \
128 "Transparency of the mosaic picture." )
130 #define X_TEXT N_("X offset")
131 #define X_LONGTEXT N_( \
132 "X coordinate of the upper left corner in the mosaic if non negative." )
134 #define Y_TEXT N_("Y offset")
135 #define Y_LONGTEXT N_( \
136 "Y coordinate of the upper left corner in the mosaic if non negative." )
138 #define CFG_PREFIX "sout-mosaic-bridge-"
141 set_shortname( N_( "Mosaic bridge" ) )
142 set_description(N_("Mosaic bridge stream output") )
143 set_capability( "sout output", 0 )
144 add_shortcut( "mosaic-bridge" )
146 set_category( CAT_SOUT
)
147 set_subcategory( SUBCAT_SOUT_STREAM
)
149 add_string( CFG_PREFIX
"id", "Id", ID_TEXT
, ID_LONGTEXT
,
151 add_integer( CFG_PREFIX
"width", 0, WIDTH_TEXT
,
152 WIDTH_LONGTEXT
, true )
153 add_integer( CFG_PREFIX
"height", 0, HEIGHT_TEXT
,
154 HEIGHT_LONGTEXT
, true )
155 add_string( CFG_PREFIX
"sar", "1:1", RATIO_TEXT
,
156 RATIO_LONGTEXT
, false )
157 add_string( CFG_PREFIX
"chroma", NULL
, CHROMA_TEXT
, CHROMA_LONGTEXT
,
160 add_module_list(CFG_PREFIX
"vfilter", "video filter", NULL
,
161 VFILTER_TEXT
, VFILTER_LONGTEXT
)
163 add_integer_with_range( CFG_PREFIX
"alpha", 255, 0, 255,
164 ALPHA_TEXT
, ALPHA_LONGTEXT
, false )
165 add_integer( CFG_PREFIX
"x", -1, X_TEXT
, X_LONGTEXT
, false )
166 add_integer( CFG_PREFIX
"y", -1, Y_TEXT
, Y_LONGTEXT
, false )
168 set_callbacks( Open
, Close
)
171 static int Control(sout_stream_t
*stream
, int query
, va_list args
)
177 case SOUT_STREAM_IS_SYNCHRONOUS
:
178 *va_arg(args
, bool *) = true;
188 static const struct sout_stream_operations ops
= {
189 Add
, Del
, Send
, Control
, NULL
,
192 static const char *const ppsz_sout_options
[] = {
193 "id", "width", "height", "sar", "vfilter", "chroma", "alpha", "x", "y", NULL
196 /*****************************************************************************
198 *****************************************************************************/
199 static int Open( vlc_object_t
*p_this
)
201 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
202 sout_stream_sys_t
*p_sys
;
205 config_ChainParse( p_stream
, CFG_PREFIX
, ppsz_sout_options
,
208 p_sys
= malloc( sizeof( sout_stream_sys_t
) );
212 p_stream
->p_sys
= p_sys
;
213 p_sys
->b_inited
= false;
215 p_sys
->psz_id
= var_CreateGetString( p_stream
, CFG_PREFIX
"id" );
218 var_CreateGetIntegerCommand( p_stream
, CFG_PREFIX
"height" );
219 var_AddCallback( p_stream
, CFG_PREFIX
"height", HeightCallback
, p_stream
);
222 var_CreateGetIntegerCommand( p_stream
, CFG_PREFIX
"width" );
223 var_AddCallback( p_stream
, CFG_PREFIX
"width", WidthCallback
, p_stream
);
225 var_Get( p_stream
, CFG_PREFIX
"sar", &val
);
228 char *psz_parser
= strchr( val
.psz_string
, ':' );
232 *psz_parser
++ = '\0';
233 p_sys
->i_sar_num
= atoi( val
.psz_string
);
234 p_sys
->i_sar_den
= atoi( psz_parser
);
235 vlc_ureduce( &p_sys
->i_sar_num
, &p_sys
->i_sar_den
,
236 p_sys
->i_sar_num
, p_sys
->i_sar_den
, 0 );
240 msg_Warn( p_stream
, "bad aspect ratio %s", val
.psz_string
);
241 p_sys
->i_sar_num
= p_sys
->i_sar_den
= 1;
244 free( val
.psz_string
);
248 p_sys
->i_sar_num
= p_sys
->i_sar_den
= 1;
252 val
.psz_string
= var_GetNonEmptyString( p_stream
, CFG_PREFIX
"chroma" );
253 if( val
.psz_string
&& strlen( val
.psz_string
) >= 4 )
255 memcpy( &p_sys
->i_chroma
, val
.psz_string
, 4 );
256 msg_Dbg( p_stream
, "Forcing image chroma to 0x%.8x (%4.4s)", p_sys
->i_chroma
, (char*)&p_sys
->i_chroma
);
258 free( val
.psz_string
);
260 #define INT_COMMAND( a ) do { \
261 var_Create( p_stream, CFG_PREFIX #a, \
262 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND ); \
263 var_AddCallback( p_stream, CFG_PREFIX #a, a ## Callback, \
264 p_stream ); } while(0)
265 INT_COMMAND( alpha
);
271 p_stream
->ops
= &ops
;
275 static vlc_decoder_device
* MosaicHoldDecoderDevice( struct decoder_owner
*p_owner
)
277 if ( p_owner
->dec_dev
== NULL
)
279 p_owner
->dec_dev
= vlc_decoder_device_Create(&p_owner
->dec
.obj
, NULL
);
281 return p_owner
->dec_dev
? vlc_decoder_device_Hold(p_owner
->dec_dev
) : NULL
;
284 static vlc_decoder_device
* video_get_decoder_device( decoder_t
*p_dec
)
286 if( !var_InheritBool( p_dec
, "hw-dec" ) )
289 struct decoder_owner
*p_owner
= dec_get_owner( p_dec
);
290 return MosaicHoldDecoderDevice(p_owner
);
293 /*****************************************************************************
295 *****************************************************************************/
296 static void Close( vlc_object_t
* p_this
)
298 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
299 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
301 /* Delete the callbacks */
302 var_DelCallback( p_stream
, CFG_PREFIX
"height", HeightCallback
, p_stream
);
303 var_DelCallback( p_stream
, CFG_PREFIX
"width", WidthCallback
, p_stream
);
304 var_DelCallback( p_stream
, CFG_PREFIX
"alpha", alphaCallback
, p_stream
);
305 var_DelCallback( p_stream
, CFG_PREFIX
"x", xCallback
, p_stream
);
306 var_DelCallback( p_stream
, CFG_PREFIX
"y", yCallback
, p_stream
);
308 free( p_sys
->psz_id
);
313 static void ReleaseDecoder( decoder_t
*p_dec
)
315 struct decoder_owner
*p_owner
= dec_get_owner( p_dec
);
316 if ( p_owner
->dec_dev
)
318 vlc_decoder_device_Release( p_owner
->dec_dev
);
319 p_owner
->dec_dev
= NULL
;
321 decoder_Destroy( p_dec
);
324 static vlc_decoder_device
* video_filter_hold_device(vlc_object_t
*o
, void *sys
)
327 struct decoder_owner
*p_owner
= sys
;
328 return MosaicHoldDecoderDevice(p_owner
);
331 static void *Add( sout_stream_t
*p_stream
, const es_format_t
*p_fmt
)
333 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
339 if( p_sys
->b_inited
|| p_fmt
->i_cat
!= VIDEO_ES
)
342 /* Create decoder object */
343 struct decoder_owner
*p_owner
= vlc_object_create( p_stream
, sizeof( *p_owner
) );
346 p_sys
->p_decoder
= &p_owner
->dec
;
347 decoder_Init( p_sys
->p_decoder
, p_fmt
);
349 p_sys
->p_decoder
->b_frame_drop_allowed
= true;
350 p_sys
->p_decoder
->fmt_out
= p_sys
->p_decoder
->fmt_in
;
351 p_sys
->p_decoder
->fmt_out
.i_extra
= 0;
352 p_sys
->p_decoder
->fmt_out
.p_extra
= 0;
353 p_sys
->p_decoder
->pf_decode
= NULL
;
355 /* Create user specified video filters */
356 static const struct filter_video_callbacks cbs
=
358 video_new_buffer_filter
, video_filter_hold_device
,
361 psz_chain
= var_GetNonEmptyString( p_stream
, CFG_PREFIX
"vfilter" );
362 msg_Dbg( p_stream
, "psz_chain: '%s'", psz_chain
? psz_chain
: "");
365 filter_owner_t owner
= {
370 p_sys
->p_vf2
= filter_chain_NewVideo( p_stream
, false, &owner
);
378 static const struct decoder_owner_callbacks dec_cbs
=
381 .get_device
= video_get_decoder_device
,
382 .format_update
= video_update_format_decoder
,
383 .queue
= decoder_queue_video
,
386 p_sys
->p_decoder
->cbs
= &dec_cbs
;
388 p_owner
->p_stream
= p_stream
;
389 //p_sys->p_decoder->p_cfg = p_sys->p_video_cfg;
391 p_sys
->p_decoder
->p_module
=
392 module_need_var( p_sys
->p_decoder
, "video decoder", "codec" );
394 if( !p_sys
->p_decoder
->p_module
)
396 msg_Err( p_stream
, "cannot find decoder" );
397 ReleaseDecoder( p_sys
->p_decoder
);
401 p_sys
->b_inited
= true;
402 vlc_global_lock( VLC_MOSAIC_MUTEX
);
404 p_bridge
= GetBridge( p_stream
);
405 if ( p_bridge
== NULL
)
407 vlc_object_t
*p_libvlc
= VLC_OBJECT( vlc_object_instance(p_stream
) );
410 p_bridge
= xmalloc( sizeof( bridge_t
) );
412 var_Create( p_libvlc
, "mosaic-struct", VLC_VAR_ADDRESS
);
413 val
.p_address
= p_bridge
;
414 var_Set( p_libvlc
, "mosaic-struct", val
);
416 p_bridge
->i_es_num
= 0;
417 p_bridge
->pp_es
= NULL
;
420 for ( i
= 0; i
< p_bridge
->i_es_num
; i
++ )
422 if ( p_bridge
->pp_es
[i
]->b_empty
)
426 if ( i
== p_bridge
->i_es_num
)
428 p_bridge
->pp_es
= xrealloc( p_bridge
->pp_es
,
429 (p_bridge
->i_es_num
+ 1) * sizeof(bridged_es_t
*) );
430 p_bridge
->i_es_num
++;
431 p_bridge
->pp_es
[i
] = xmalloc( sizeof(bridged_es_t
) );
434 p_sys
->p_es
= p_es
= p_bridge
->pp_es
[i
];
436 p_es
->i_alpha
= var_GetInteger( p_stream
, CFG_PREFIX
"alpha" );
437 p_es
->i_x
= var_GetInteger( p_stream
, CFG_PREFIX
"x" );
438 p_es
->i_y
= var_GetInteger( p_stream
, CFG_PREFIX
"y" );
440 //p_es->fmt = *p_fmt;
441 p_es
->psz_id
= p_sys
->psz_id
;
442 vlc_picture_chain_Init( &p_es
->pictures
);
443 p_es
->b_empty
= false;
445 vlc_global_unlock( VLC_MOSAIC_MUTEX
);
447 if ( p_sys
->i_height
|| p_sys
->i_width
)
449 p_sys
->p_image
= image_HandlerCreate( p_stream
);
453 p_sys
->p_image
= NULL
;
456 msg_Dbg( p_stream
, "mosaic bridge id=%s pos=%d", p_es
->psz_id
, i
);
461 static void Del( sout_stream_t
*p_stream
, void *id
)
464 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
467 bool b_last_es
= true;
470 if( !p_sys
->b_inited
)
473 ReleaseDecoder( p_sys
->p_decoder
);
475 /* Destroy user specified video filters */
477 filter_chain_Delete( p_sys
->p_vf2
);
479 vlc_global_lock( VLC_MOSAIC_MUTEX
);
481 p_bridge
= GetBridge( p_stream
);
484 p_es
->b_empty
= true;
485 while ( !vlc_picture_chain_IsEmpty( &p_es
->pictures
) )
487 picture_t
*es_picture
= vlc_picture_chain_PopFront( &p_es
->pictures
);
488 picture_Release( es_picture
);
491 for ( i
= 0; i
< p_bridge
->i_es_num
; i
++ )
493 if ( !p_bridge
->pp_es
[i
]->b_empty
)
502 vlc_object_t
*p_libvlc
= VLC_OBJECT( vlc_object_instance(p_stream
) );
503 for ( i
= 0; i
< p_bridge
->i_es_num
; i
++ )
504 free( p_bridge
->pp_es
[i
] );
505 free( p_bridge
->pp_es
);
507 var_Destroy( p_libvlc
, "mosaic-struct" );
510 vlc_global_unlock( VLC_MOSAIC_MUTEX
);
512 if ( p_sys
->p_image
)
514 image_HandlerDelete( p_sys
->p_image
);
517 p_sys
->b_inited
= false;
520 static void decoder_queue_video( decoder_t
*p_dec
, picture_t
*p_pic
)
522 struct decoder_owner
*p_owner
= dec_get_owner( p_dec
);
523 sout_stream_t
*p_stream
= p_owner
->p_stream
;
524 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
525 picture_t
*p_new_pic
;
526 const video_format_t
*p_fmt_in
= &p_sys
->p_decoder
->fmt_out
.video
;
528 if( p_sys
->i_height
|| p_sys
->i_width
)
530 video_format_t fmt_out
;
532 video_format_Init( &fmt_out
, p_sys
->i_chroma
? p_sys
->i_chroma
: VLC_CODEC_I420
);
534 const unsigned i_fmt_in_aspect
=
535 (int64_t)VOUT_ASPECT_FACTOR
*
536 p_fmt_in
->i_sar_num
* p_fmt_in
->i_width
/
537 (p_fmt_in
->i_sar_den
* p_fmt_in
->i_height
);
538 if ( !p_sys
->i_height
)
540 fmt_out
.i_width
= p_sys
->i_width
;
541 fmt_out
.i_height
= (p_sys
->i_width
* VOUT_ASPECT_FACTOR
542 * p_sys
->i_sar_num
/ p_sys
->i_sar_den
/ i_fmt_in_aspect
)
545 else if ( !p_sys
->i_width
)
547 fmt_out
.i_height
= p_sys
->i_height
;
548 fmt_out
.i_width
= (p_sys
->i_height
* i_fmt_in_aspect
549 * p_sys
->i_sar_den
/ p_sys
->i_sar_num
/ VOUT_ASPECT_FACTOR
)
554 fmt_out
.i_width
= p_sys
->i_width
;
555 fmt_out
.i_height
= p_sys
->i_height
;
557 fmt_out
.i_visible_width
= fmt_out
.i_width
;
558 fmt_out
.i_visible_height
= fmt_out
.i_height
;
560 p_new_pic
= image_Convert( p_sys
->p_image
,
561 p_pic
, p_fmt_in
, &fmt_out
);
562 video_format_Clean( &fmt_out
);
563 if( p_new_pic
== NULL
)
565 msg_Err( p_stream
, "image conversion failed" );
566 picture_Release( p_pic
);
572 /* TODO: chroma conversion if needed */
573 video_format_t pic_fmt
= p_pic
->format
;
574 pic_fmt
.i_sar_num
= p_fmt_in
->i_sar_num
;
575 pic_fmt
.i_sar_den
= p_fmt_in
->i_sar_den
;
577 p_new_pic
= picture_NewFromFormat( &pic_fmt
);
580 picture_Release( p_pic
);
581 msg_Err( p_stream
, "image allocation failed" );
585 picture_Copy( p_new_pic
, p_pic
);
587 picture_Release( p_pic
);
590 p_new_pic
= filter_chain_VideoFilter( p_sys
->p_vf2
, p_new_pic
);
592 /* push the picture in the mosaic-struct structure */
593 bridged_es_t
*p_es
= p_sys
->p_es
;
594 vlc_global_lock( VLC_MOSAIC_MUTEX
);
595 vlc_picture_chain_Append( &p_es
->pictures
, p_new_pic
);
596 vlc_global_unlock( VLC_MOSAIC_MUTEX
);
599 static int Send( sout_stream_t
*p_stream
, void *id
, block_t
*p_buffer
)
601 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
603 if ( (sout_stream_sys_t
*)id
!= p_sys
)
605 block_ChainRelease( p_buffer
);
609 int ret
= p_sys
->p_decoder
->pf_decode( p_sys
->p_decoder
, p_buffer
);
610 return ret
== VLCDEC_SUCCESS
? VLC_SUCCESS
: VLC_EGENERIC
;
613 static int video_update_format_decoder( decoder_t
*p_dec
, vlc_video_context
*vctx
)
615 struct decoder_owner
*p_owner
= dec_get_owner( p_dec
);
616 sout_stream_sys_t
*p_sys
= p_owner
->p_stream
->p_sys
;
619 // update the filter after the format changed/is known
620 char *psz_chain
= var_GetNonEmptyString( p_owner
->p_stream
, CFG_PREFIX
"vfilter" );
621 msg_Dbg( p_owner
->p_stream
, "update filter: '%s'",
622 psz_chain
? psz_chain
: "" );
626 es_format_InitFromVideo( &fmt
, &p_dec
->fmt_out
.video
);
627 if( p_sys
->i_chroma
)
629 fmt
.video
.i_chroma
= p_sys
->i_chroma
;
630 vctx
= NULL
; // CPU chroma, no video context
632 filter_chain_Reset( p_sys
->p_vf2
, &fmt
, vctx
, &fmt
);
633 es_format_Clean( &fmt
);
634 filter_chain_AppendFromString( p_sys
->p_vf2
, psz_chain
);
641 static picture_t
*video_new_buffer_filter( filter_t
*p_filter
)
643 return picture_NewFromFormat( &p_filter
->fmt_out
.video
);
646 /**********************************************************************
647 * Callback to update (some) params on the fly
648 **********************************************************************/
649 static int HeightCallback( vlc_object_t
*p_this
, char const *psz_var
,
650 vlc_value_t oldval
, vlc_value_t newval
,
653 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
654 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
655 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
657 /* We create the handler before updating the value in p_sys
658 * so we don't have to worry about locking */
659 if( !p_sys
->p_image
&& newval
.i_int
)
660 p_sys
->p_image
= image_HandlerCreate( p_stream
);
661 p_sys
->i_height
= newval
.i_int
;
666 static int WidthCallback( vlc_object_t
*p_this
, char const *psz_var
,
667 vlc_value_t oldval
, vlc_value_t newval
,
670 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
671 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
672 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
674 /* We create the handler before updating the value in p_sys
675 * so we don't have to worry about locking */
676 if( !p_sys
->p_image
&& newval
.i_int
)
677 p_sys
->p_image
= image_HandlerCreate( p_stream
);
678 p_sys
->i_width
= newval
.i_int
;
683 static int alphaCallback( vlc_object_t
*p_this
, char const *psz_var
,
684 vlc_value_t oldval
, vlc_value_t newval
,
687 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
688 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
689 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
692 p_sys
->p_es
->i_alpha
= newval
.i_int
;
697 static int xCallback( vlc_object_t
*p_this
, char const *psz_var
,
698 vlc_value_t oldval
, vlc_value_t newval
,
701 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
702 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
703 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
706 p_sys
->p_es
->i_x
= newval
.i_int
;
711 static int yCallback( vlc_object_t
*p_this
, char const *psz_var
,
712 vlc_value_t oldval
, vlc_value_t newval
,
715 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
); VLC_UNUSED(psz_var
);
716 sout_stream_t
*p_stream
= (sout_stream_t
*)p_data
;
717 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
720 p_sys
->p_es
->i_y
= newval
.i_int
;