Commit 46e872e4 authored by Laurent Aimar's avatar Laurent Aimar

* all: implement more es_out_* control, audio-channel and spu-channel are

 implemented.
parent fc1221c1
......@@ -2,7 +2,7 @@
* ninput.h
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ninput.h,v 1.18 2003/11/21 00:38:01 gbazin Exp $
* $Id: ninput.h,v 1.19 2003/11/27 04:11:40 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -26,17 +26,36 @@
#include "vlc_es.h"
enum es_out_mode_e
{
ES_OUT_MODE_NONE, /* don't select anything */
ES_OUT_MODE_ALL, /* eg for stream output */
ES_OUT_MODE_AUTO /* best audio/video or for input follow audio-channel, spu-channel */
};
enum es_out_query_e
{
ES_OUT_SET_SELECT, /* arg1= es_out_id_t* arg2=vlc_bool_t */
ES_OUT_GET_SELECT /* arg1= es_out_id_t* arg2=vlc_bool_t* */
/* activate apply of mode */
ES_OUT_SET_ACTIVE, /* arg1= vlc_bool_t */
/* see if mode is currently aplied or not */
ES_OUT_GET_ACTIVE, /* arg1= vlc_bool_t* */
/* set/get mode */
ES_OUT_SET_MODE, /* arg1= int */
ES_OUT_GET_MODE, /* arg2= int* */
/* set es selected for the es category(audio/video/spu) */
ES_OUT_SET_ES, /* arg1= es_out_id_t* */
/* force selection/unselection of the ES (bypass current mode)*/
ES_OUT_SET_ES_STATE,/* arg1= es_out_id_t* arg2=vlc_bool_t */
ES_OUT_GET_ES_STATE,/* arg1= es_out_id_t* arg2=vlc_bool_t* */
};
struct es_out_t
{
es_out_id_t *(*pf_add) ( es_out_t *, es_format_t * );
int (*pf_send) ( es_out_t *, es_out_id_t *, block_t * );
int (*pf_send_pes)( es_out_t *, es_out_id_t *, pes_packet_t * );
void (*pf_del) ( es_out_t *, es_out_id_t * );
int (*pf_control)( es_out_t *, int i_query, va_list );
......@@ -52,15 +71,11 @@ static inline void es_out_Del( es_out_t *out, es_out_id_t *id )
out->pf_del( out, id );
}
static inline int es_out_Send( es_out_t *out, es_out_id_t *id,
block_t *p_block )
block_t *p_block )
{
return out->pf_send( out, id, p_block );
}
static inline int es_out_SendPES( es_out_t *out, es_out_id_t *id,
pes_packet_t *p_pes )
{
return out->pf_send_pes( out, id, p_pes );
}
static inline int es_out_vaControl( es_out_t *out, int i_query, va_list args )
{
return out->pf_control( out, i_query, args );
......
......@@ -2,7 +2,7 @@
* avi.c : AVI file Stream input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: avi.c,v 1.77 2003/11/26 08:18:09 gbazin Exp $
* $Id: avi.c,v 1.78 2003/11/27 04:11:40 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
......@@ -469,7 +469,7 @@ static int Demux_Seekable( input_thread_t *p_input )
avi_track_t *tk = p_sys->track[i_track];
vlc_bool_t b;
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT, tk->p_es, &b );
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
if( b && !tk->b_activated )
{
if( p_sys->b_seekable)
......@@ -794,7 +794,7 @@ static int Demux_UnSeekable( input_thread_t *p_input )
avi_track_t *tk = p_sys->track[i_stream];
vlc_bool_t b;
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT, tk->p_es, &b );
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
if( b && tk->i_cat == VIDEO_ES )
{
......
......@@ -2,7 +2,7 @@
* mkv.cpp : matroska demuxer
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: mkv.cpp,v 1.44 2003/11/23 13:15:27 gbazin Exp $
* $Id: mkv.cpp,v 1.45 2003/11/27 04:11:40 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -1401,7 +1401,7 @@ static void BlockDecode( input_thread_t *p_input, KaxBlock *block, mtime_t i_pts
return;
}
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT, tk.p_es, &b );
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk.p_es, &b );
if( !b )
{
tk.b_inited = VLC_FALSE;
......
......@@ -2,7 +2,7 @@
* ogg.c : ogg stream input module for vlc
*****************************************************************************
* Copyright (C) 2001-2003 VideoLAN
* $Id: ogg.c,v 1.47 2003/11/26 08:18:09 gbazin Exp $
* $Id: ogg.c,v 1.48 2003/11/27 04:11:40 fenrir Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -359,7 +359,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
}
/* Check the ES is selected */
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT,
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE,
p_stream->p_es, &b_selected );
if( b_selected && !p_stream->b_activated )
......
......@@ -2,7 +2,7 @@
* rawdv.c : raw dv input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: rawdv.c,v 1.12 2003/11/24 19:19:02 fenrir Exp $
* $Id: rawdv.c,v 1.13 2003/11/27 04:11:40 fenrir Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -297,9 +297,9 @@ static int Demux( input_thread_t * p_input )
return 0;
}
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT,
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE,
p_sys->p_es_audio, &b_audio );
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT,
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE,
p_sys->p_es_video, &b_video );
p_block->i_dts =
......
......@@ -2,7 +2,7 @@
* sub.c
*****************************************************************************
* Copyright (C) 1999-2003 VideoLAN
* $Id: sub.c,v 1.38 2003/11/21 00:38:01 gbazin Exp $
* $Id: sub.c,v 1.39 2003/11/27 04:11:40 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -502,7 +502,7 @@ static int sub_demux( subtitle_demux_t *p_sub, mtime_t i_maxdate )
input_thread_t *p_input = p_sub->p_input;
vlc_bool_t b;
es_out_Control( p_input->p_es_out, ES_OUT_GET_SELECT, p_sub->p_es, &b );
es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, p_sub->p_es, &b );
if( b && !p_sub->i_previously_selected )
{
p_sub->i_previously_selected = 1;
......
......@@ -2,7 +2,7 @@
* es_out.c: Es Out handler for input.
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: es_out.c,v 1.1 2003/11/24 20:50:45 fenrir Exp $
* $Id: es_out.c,v 1.2 2003/11/27 04:11:40 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -35,25 +35,43 @@
/*****************************************************************************
* Local prototypes
*****************************************************************************/
struct es_out_id_t
{
int i_channel;
es_descriptor_t *p_es;
};
struct es_out_sys_t
{
input_thread_t *p_input;
/* all es */
int i_id;
es_out_id_t **id;
vlc_bool_t i_audio;
vlc_bool_t i_video;
};
int i_es;
es_out_id_t **es;
struct es_out_id_t
{
es_descriptor_t *p_es;
/* mode gestion */
vlc_bool_t b_active;
int i_mode;
/* es count */
int i_audio;
int i_video;
int i_sub;
/* es to select */
int i_audio_last;
int i_sub_last;
/* current main es */
es_out_id_t *p_es_audio;
es_out_id_t *p_es_video;
es_out_id_t *p_es_sub;
};
static es_out_id_t *EsOutAdd ( es_out_t *, es_format_t * );
static int EsOutSend ( es_out_t *, es_out_id_t *, block_t * );
static int EsOutSendPES( es_out_t *, es_out_id_t *, pes_packet_t * );
static void EsOutDel ( es_out_t *, es_out_id_t * );
static int EsOutControl( es_out_t *, int i_query, va_list );
......@@ -63,20 +81,40 @@ static int EsOutControl( es_out_t *, int i_query, va_list );
*****************************************************************************/
es_out_t *input_EsOutNew( input_thread_t *p_input )
{
es_out_t *out = malloc( sizeof( es_out_t ) );
es_out_t *out = malloc( sizeof( es_out_t ) );
es_out_sys_t *p_sys = malloc( sizeof( es_out_sys_t ) );
vlc_value_t val;
out->pf_add = EsOutAdd;
out->pf_send = EsOutSend;
out->pf_send_pes= EsOutSendPES;
out->pf_del = EsOutDel;
out->pf_control = EsOutControl;
out->p_sys = p_sys;
p_sys->p_input = p_input;
p_sys->b_active = VLC_FALSE;
p_sys->i_mode = ES_OUT_MODE_AUTO;
p_sys->i_id = 1;
p_sys->i_es = 0;
p_sys->es = NULL;
p_sys->i_audio = 0;
p_sys->i_video = 0;
p_sys->i_sub = 0;
var_Get( p_input, "audio-channel", &val );
p_sys->i_audio_last = val.i_int;
var_Get( p_input, "spu-channel", &val );
p_sys->i_sub_last = val.i_int;
p_sys->p_es_audio = NULL;
p_sys->p_es_video = NULL;
p_sys->p_es_sub = NULL;
out->p_sys = malloc( sizeof( es_out_sys_t ) );
out->p_sys->p_input = p_input;
out->p_sys->i_id = 0;
out->p_sys->id = NULL;
out->p_sys->i_audio = -1;
out->p_sys->i_video = -1;
return out;
}
......@@ -88,18 +126,97 @@ void input_EsOutDelete( es_out_t *out )
es_out_sys_t *p_sys = out->p_sys;
int i;
for( i = 0; i < p_sys->i_id; i++ )
for( i = 0; i < p_sys->i_es; i++ )
{
free( p_sys->id[i] );
free( p_sys->es[i] );
}
if( p_sys->id )
if( p_sys->es )
{
free( p_sys->id );
free( p_sys->es );
}
free( p_sys );
free( out );
}
/*****************************************************************************
* EsOutSelect: Select an ES given the current mode
* XXX: you need to take a the lock before (stream.stream_lock)
*****************************************************************************/
static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
{
es_out_sys_t *p_sys = out->p_sys;
input_thread_t *p_input = p_sys->p_input;
int i_cat = es->p_es->i_cat;
if( !p_sys->b_active || ( !b_force && es->p_es->fmt.i_priority < 0 ) )
{
return;
}
if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
{
input_SelectES( p_input, es->p_es );
}
else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
{
int i_wanted = -1;
if( i_cat == AUDIO_ES )
{
if( p_sys->p_es_audio && p_sys->p_es_audio->p_es->fmt.i_priority >= es->p_es->fmt.i_priority )
{
return;
}
i_wanted = p_sys->i_audio_last >= 0 ? p_sys->i_audio_last : es->i_channel;
}
else if( i_cat == SPU_ES )
{
if( p_sys->p_es_sub && p_sys->p_es_sub->p_es->fmt.i_priority >= es->p_es->fmt.i_priority )
{
return;
}
i_wanted = p_sys->i_sub_last;
}
else if( i_cat == VIDEO_ES )
{
i_wanted = es->i_channel;
}
if( i_wanted == es->i_channel )
{
input_SelectES( p_input, es->p_es );
}
}
/* FIXME TODO handle priority here */
if( es->p_es->p_dec )
{
if( i_cat == AUDIO_ES )
{
if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
p_sys->p_es_audio && p_sys->p_es_audio->p_es->p_dec )
{
input_UnselectES( p_input, p_sys->p_es_audio->p_es );
}
p_sys->p_es_audio = es;
}
else if( i_cat == SPU_ES )
{
if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
p_sys->p_es_sub && p_sys->p_es_sub->p_es->p_dec )
{
input_UnselectES( p_input, p_sys->p_es_sub->p_es );
}
p_sys->p_es_sub = es;
}
else if( i_cat == VIDEO_ES )
{
p_sys->p_es_video = es;
}
}
}
/*****************************************************************************
* EsOutAdd:
*****************************************************************************/
......@@ -107,7 +224,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
{
es_out_sys_t *p_sys = out->p_sys;
input_thread_t *p_input = p_sys->p_input;
es_out_id_t *id = malloc( sizeof( es_out_id_t ) );
es_out_id_t *es = malloc( sizeof( es_out_id_t ) );
pgrm_descriptor_t *p_prgm = NULL;
char psz_cat[strlen( "Stream " ) + 10];
input_info_category_t *p_cat;
......@@ -131,13 +248,13 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
}
}
id->p_es = input_AddES( p_input,
es->p_es = input_AddES( p_input,
p_prgm,
1 + out->p_sys->i_id,
out->p_sys->i_id,
fmt->i_cat,
fmt->psz_description, 0 );
id->p_es->i_stream_id = 1 + out->p_sys->i_id;
id->p_es->i_fourcc = fmt->i_codec;
es->p_es->i_stream_id = out->p_sys->i_id;
es->p_es->i_fourcc = fmt->i_codec;
switch( fmt->i_cat )
{
......@@ -157,7 +274,9 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
{
memcpy( &p_wf[1], fmt->p_extra, fmt->i_extra );
}
id->p_es->p_waveformatex = p_wf;
es->p_es->p_waveformatex = p_wf;
es->i_channel = p_sys->i_audio;
break;
}
case VIDEO_ES:
......@@ -181,7 +300,9 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
{
memcpy( &p_bih[1], fmt->p_extra, fmt->i_extra );
}
id->p_es->p_bitmapinfoheader = p_bih;
es->p_es->p_bitmapinfoheader = p_bih;
es->i_channel = p_sys->i_video;
break;
}
case SPU_ES:
......@@ -190,43 +311,24 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
memset( p_sub, 0, sizeof( subtitle_data_t ) );
if( fmt->i_extra > 0 )
{
p_sub->psz_header = malloc( fmt->i_extra );
p_sub->psz_header = malloc( fmt->i_extra + 1 );
memcpy( p_sub->psz_header, fmt->p_extra , fmt->i_extra );
/* just to be sure */
((uint8_t*)fmt->p_extra)[fmt->i_extra] = '\0';
}
/* FIXME beuuuuuurk */
id->p_es->p_demux_data = p_sub;
es->p_es->p_demux_data = p_sub;
es->i_channel = p_sys->i_sub;
break;
}
default:
es->i_channel = 0;
break;
}
if( fmt->i_cat == AUDIO_ES && fmt->i_priority > out->p_sys->i_audio )
{
if( out->p_sys->i_audio >= 0 )
{
msg_Err( p_input, "FIXME unselect es in es_out_Add" );
}
input_SelectES( p_input, id->p_es );
if( id->p_es->p_dec )
{
out->p_sys->i_audio = fmt->i_priority;
}
}
else if( fmt->i_cat == VIDEO_ES && fmt->i_priority > out->p_sys->i_video )
{
if( out->p_sys->i_video >= 0 )
{
msg_Err( p_input, "FIXME unselect es in es_out_Add" );
}
input_SelectES( p_input, id->p_es );
if( id->p_es->p_dec )
{
out->p_sys->i_video = fmt->i_priority;
}
}
sprintf( psz_cat, _("Stream %d"), out->p_sys->i_id );
sprintf( psz_cat, _("Stream %d"), out->p_sys->i_id - 1 );
if( ( p_cat = input_InfoCategory( p_input, psz_cat ) ) )
{
/* Add information */
......@@ -284,74 +386,99 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
break;
}
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
id->p_es->fmt = *fmt;
TAB_APPEND( out->p_sys->i_id, out->p_sys->id, id );
return id;
}
/*****************************************************************************
* EsOutSend:
*****************************************************************************/
static int EsOutSend( es_out_t *out, es_out_id_t *id, block_t *p_block )
{
if( id->p_es->p_dec )
/* Apply mode
* XXX change that when we do group too */
if( 1 )
{
input_DecodeBlock( id->p_es->p_dec, p_block );
EsOutSelect( out, es, VLC_FALSE );
}
else
vlc_mutex_unlock( &p_input->stream.stream_lock );
es->p_es->fmt = *fmt;
TAB_APPEND( out->p_sys->i_es, out->p_sys->es, es );
p_sys->i_id++; /* always incremented */
switch( fmt->i_cat )
{
block_Release( p_block );
case AUDIO_ES:
p_sys->i_audio++;
break;
case SPU_ES:
p_sys->i_sub++;
break;
case VIDEO_ES:
p_sys->i_video++;
break;
}
return VLC_SUCCESS;
return es;
}
/*****************************************************************************
* EsOutSendPES:
* EsOutSend:
*****************************************************************************/
static int EsOutSendPES( es_out_t *out, es_out_id_t *id, pes_packet_t *p_pes )
static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
{
if( id->p_es->p_dec )
vlc_mutex_lock( &out->p_sys->p_input->stream.stream_lock );
if( es->p_es->p_dec )
{
input_DecodePES( id->p_es->p_dec, p_pes );
input_DecodeBlock( es->p_es->p_dec, p_block );
}
else
{
input_DeletePES( out->p_sys->p_input->p_method_data, p_pes );
block_Release( p_block );
}
vlc_mutex_unlock( &out->p_sys->p_input->stream.stream_lock );
return VLC_SUCCESS;
}
/*****************************************************************************
* EsOutDel:
*****************************************************************************/
static void EsOutDel( es_out_t *out, es_out_id_t *id )
static void EsOutDel( es_out_t *out, es_out_id_t *es )
{
es_out_sys_t *p_sys = out->p_sys;
TAB_REMOVE( p_sys->i_id, p_sys->id, id );
TAB_REMOVE( p_sys->i_es, p_sys->es, es );
switch( es->p_es->i_cat )
{
case AUDIO_ES:
p_sys->i_audio--;
break;
case SPU_ES:
p_sys->i_sub--;
break;
case VIDEO_ES:
p_sys->i_video--;
break;
}
/* We don't try to reselect */
vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
if( id->p_es->p_dec )
if( es->p_es->p_dec )
{
input_UnselectES( p_sys->p_input, id->p_es );
input_UnselectES( p_sys->p_input, es->p_es );
}
if( id->p_es->p_waveformatex )
if( es->p_es->p_waveformatex )
{
free( id->p_es->p_waveformatex );
id->p_es->p_waveformatex = NULL;
free( es->p_es->p_waveformatex );
es->p_es->p_waveformatex = NULL;
}
if( id->p_es->p_bitmapinfoheader )
if( es->p_es->p_bitmapinfoheader )
{
free( id->p_es->p_bitmapinfoheader );
id->p_es->p_bitmapinfoheader = NULL;
free( es->p_es->p_bitmapinfoheader );
es->p_es->p_bitmapinfoheader = NULL;
}
input_DelES( p_sys->p_input, id->p_es );
input_DelES( p_sys->p_input, es->p_es );
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
free( id );
free( es );
}
/*****************************************************************************
......@@ -361,30 +488,94 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
{
es_out_sys_t *p_sys = out->p_sys;
vlc_bool_t b, *pb;
es_out_id_t *id;
int i, *pi;
es_out_id_t *es;
switch( i_query )
{
case ES_OUT_SET_SELECT:
case ES_OUT_SET_ES_STATE:
vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
id = (es_out_id_t*) va_arg( args, es_out_id_t * );
es = (es_out_id_t*) va_arg( args, es_out_id_t * );
b = (vlc_bool_t) va_arg( args, vlc_bool_t );
if( b && id->p_es->p_dec == NULL )
if( b && es->p_es->p_dec == NULL )
{
input_SelectES( p_sys->p_input, id->p_es );
input_SelectES( p_sys->p_input, es->p_es );
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
return id->p_es->p_dec ? VLC_SUCCESS : VLC_EGENERIC;
return es->p_es->p_dec ? VLC_SUCCESS : VLC_EGENERIC;
}
else if( !b && id->p_es->p_dec )
else if( !b && es->p_es->p_dec )
{
input_UnselectES( p_sys->p_input, id->p_es );
input_UnselectES( p_sys->p_input, es->p_es );
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
return VLC_SUCCESS;
}
case ES_OUT_GET_SELECT:
id = (es_out_id_t*) va_arg( args, es_out_id_t * );
case ES_OUT_GET_ES_STATE:
es = (es_out_id_t*) va_arg( args, es_out_id_t * );
pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
*pb = id->p_es->p_dec ? VLC_TRUE : VLC_FALSE;
*pb = es->p_es->p_dec ? VLC_TRUE : VLC_FALSE;
return VLC_SUCCESS;
case ES_OUT_SET_ACTIVE:
b = (vlc_bool_t) va_arg( args, vlc_bool_t );
p_sys->b_active = b;
return VLC_SUCCESS;
case ES_OUT_GET_ACTIVE:
pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
*pb = p_sys->b_active;
return VLC_SUCCESS;
case ES_OUT_SET_MODE:
i = (int) va_arg( args, int );
if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL || i == ES_OUT_MODE_AUTO )
{
p_sys->i_mode = i;
/* Reapply policy mode */
vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
for( i = 0; i < p_sys->i_es; i++ )
{
if( p_sys->es[i]->p_es->p_dec )
{
input_UnselectES( p_sys->p_input, p_sys->es[i]->p_es );
}
}
for( i = 0; i < p_sys->i_es; i++ )
{
EsOutSelect( out, p_sys->es[i], VLC_FALSE );
}
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
return VLC_SUCCESS;
}
return VLC_EGENERIC;
case ES_OUT_GET_MODE:
pi = (int*) va_arg( args, int* );
*pi = p_sys->i_mode;
return VLC_SUCCESS;