Ejemplo n.º 1
0
Archivo: osd.c Proyecto: 0xheart0/vlc
/*
 * OSD menu
 */
int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;

    id->p_decoder->fmt_in.i_cat = SPU_ES;
    id->p_encoder->fmt_out.psz_language = strdup( "osd" );

    if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
    {
        msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
                 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
                 (char*)&p_sys->i_osdcodec );

        /* Complete destination format */
        id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;

        /* Open encoder */
        es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
                        VLC_CODEC_YUVA );
        id->p_encoder->fmt_in.psz_language = strdup( "osd" );

        id->p_encoder->p_cfg = p_sys->p_osd_cfg;

        id->p_encoder->p_module =
            module_need( id->p_encoder, "encoder", p_sys->psz_osdenc, true );

        if( !id->p_encoder->p_module )
        {
            msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_osdenc );
            goto error;
        }

        /* open output stream */
        id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
        id->b_transcode = true;

        if( !id->id ) goto error;
    }
    else
    {
        msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
                 (char*)&id->p_decoder->fmt_out.i_codec );
        id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_decoder->fmt_out );
        id->b_transcode = false;

        if( !id->id ) goto error;
    }

    if( !p_sys->p_spu )
        p_sys->p_spu = spu_Create( p_stream );

    return VLC_SUCCESS;

 error:
    msg_Err( p_stream, "starting osd encoding thread failed" );
    if( id->p_encoder->p_module )
            module_unneed( id->p_encoder, id->p_encoder->p_module );
    p_sys->b_osd = false;
    return VLC_EGENERIC;
}
Ejemplo n.º 2
0
Archivo: spu.c Proyecto: CSRedRat/vlc
int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;

    /*
     * Open decoder
     */

    /* Initialization of decoder structures */
    id->p_decoder->pf_decode_sub = NULL;
    id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
    id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
    id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
    /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */

    id->p_decoder->p_module =
        module_need( id->p_decoder, "decoder", "$codec", false );

    if( !id->p_decoder->p_module )
    {
        msg_Err( p_stream, "cannot find spu decoder" );
        return VLC_EGENERIC;
    }

    if( !p_sys->b_soverlay )
    {
        /* Open encoder */
        /* Initialization of encoder format structures */
        es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
                        id->p_decoder->fmt_in.i_codec );

        id->p_encoder->p_cfg = p_sys->p_spu_cfg;

        id->p_encoder->p_module =
            module_need( id->p_encoder, "encoder", p_sys->psz_senc, true );

        if( !id->p_encoder->p_module )
        {
            module_unneed( id->p_decoder, id->p_decoder->p_module );
            msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_senc );
            return VLC_EGENERIC;
        }
    }

    if( !p_sys->p_spu )
        p_sys->p_spu = spu_Create( p_stream );

    return VLC_SUCCESS;
}
Ejemplo n.º 3
0
Archivo: osd.c Proyecto: 0xheart0/vlc
int transcode_osd_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                                  block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    subpicture_t *p_subpic = NULL;

    /* Check if we have a subpicture to send */
    if( p_sys->p_spu && in->i_dts > VLC_TS_INVALID )
    {
        video_format_t fmt;
        video_format_Init( &fmt, 0 );
        video_format_Setup( &fmt, 0, 720, 576, 720, 576, 1, 1 );
        p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt, in->i_dts, in->i_dts, false );
    }
    else
    {
        msg_Warn( p_stream, "spu channel not initialized, doing it now" );
        if( !p_sys->p_spu )
            p_sys->p_spu = spu_Create( p_stream );
    }

    if( p_subpic )
    {
        block_t *p_block = NULL;

        if( p_sys->b_master_sync && p_sys->i_master_drift )
        {
            p_subpic->i_start -= p_sys->i_master_drift;
            if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
        }

        p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
        subpicture_Delete( p_subpic );
        if( p_block )
        {
            p_block->i_dts = p_block->i_pts = in->i_dts;
            block_ChainAppend( out, p_block );
            return VLC_SUCCESS;
        }
    }
    return VLC_EGENERIC;
}
Ejemplo n.º 4
0
/*****************************************************************************
 * 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;
    char              *psz_string;

    if( !p_stream->p_next )
    {
        msg_Err( p_stream, "cannot create chain" );
        return VLC_EGENERIC;
    }
    p_sys = calloc( 1, sizeof( *p_sys ) );
    p_sys->i_master_drift = 0;

    config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
                   p_stream->p_cfg );

    /* Audio transcoding parameters */
    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "aenc" );
    p_sys->psz_aenc = NULL;
    p_sys->p_audio_cfg = NULL;
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
                                       psz_string );
        free( psz_next );
    }
    free( psz_string );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "acodec" );
    p_sys->i_acodec = 0;
    if( psz_string && *psz_string )
    {
        char fcc[4] = "    ";
        memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
        p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
    }
    free( psz_string );

    p_sys->psz_alang = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "alang" );

    p_sys->i_abitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ab" );
    if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;

    p_sys->i_sample_rate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "samplerate" );

    p_sys->i_channels = var_GetInteger( p_stream, SOUT_CFG_PREFIX "channels" );

    if( p_sys->i_acodec )
    {
        if( ( p_sys->i_acodec == VLC_CODEC_MP3 ||
              p_sys->i_acodec == VLC_CODEC_MP2 ||
              p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 )
        {
            msg_Warn( p_stream, "%d channels invalid for mp2/mp3, forcing to 2",
                      p_sys->i_channels );
            p_sys->i_channels = 2;
        }
        msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
                 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
                 p_sys->i_channels, p_sys->i_abitrate / 1000 );
    }

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "afilter" );
    if( psz_string && *psz_string )
        p_sys->psz_af = strdup( psz_string );
    else
        p_sys->psz_af = NULL;
    free( psz_string );

    /* Video transcoding parameters */
    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "venc" );
    p_sys->psz_venc = NULL;
    p_sys->p_video_cfg = NULL;
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
                                   psz_string );
        free( psz_next );
    }
    free( psz_string );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vcodec" );
    p_sys->i_vcodec = 0;
    if( psz_string && *psz_string )
    {
        char fcc[4] = "    ";
        memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
        p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
    }
    free( psz_string );

    p_sys->i_vbitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "vb" );
    if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;

    p_sys->f_scale = var_GetFloat( p_stream, SOUT_CFG_PREFIX "scale" );

    p_sys->f_fps = var_GetFloat( p_stream, SOUT_CFG_PREFIX "fps" );

    p_sys->b_hurry_up = var_GetBool( p_stream, SOUT_CFG_PREFIX "hurry-up" );

    p_sys->i_width = var_GetInteger( p_stream, SOUT_CFG_PREFIX "width" );

    p_sys->i_height = var_GetInteger( p_stream, SOUT_CFG_PREFIX "height" );

    p_sys->i_maxwidth = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxwidth" );

    p_sys->i_maxheight = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxheight" );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vfilter" );
    if( psz_string && *psz_string )
        p_sys->psz_vf2 = strdup(psz_string );
    else
        p_sys->psz_vf2 = NULL;
    free( psz_string );

    p_sys->b_deinterlace = var_GetBool( p_stream, SOUT_CFG_PREFIX "deinterlace" );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "deinterlace-module" );
    p_sys->psz_deinterlace = NULL;
    p_sys->p_deinterlace_cfg = NULL;
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
                                   &p_sys->p_deinterlace_cfg,
                                   psz_string );
        free( psz_next );
    }
    free( psz_string );

    p_sys->i_threads = var_GetInteger( p_stream, SOUT_CFG_PREFIX "threads" );
    p_sys->b_high_priority = var_GetBool( p_stream, SOUT_CFG_PREFIX "high-priority" );

    if( p_sys->i_vcodec )
    {
        msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
                 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
                 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
    }

    /* Subpictures transcoding parameters */
    p_sys->p_spu = NULL;
    p_sys->p_spu_blend = NULL;
    p_sys->psz_senc = NULL;
    p_sys->p_spu_cfg = NULL;
    p_sys->i_scodec = 0;

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "senc" );
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
                                   psz_string );
        free( psz_next );
    }
    free( psz_string );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "scodec" );
    if( psz_string && *psz_string )
    {
        char fcc[4] = "    ";
        memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
        p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
    }
    free( psz_string );

    if( p_sys->i_scodec )
    {
        msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
    }

    p_sys->b_soverlay = var_GetBool( p_stream, SOUT_CFG_PREFIX "soverlay" );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "sfilter" );
    if( psz_string && *psz_string )
    {
        p_sys->p_spu = spu_Create( p_stream );
        if( p_sys->p_spu )
            spu_ChangeSources( p_sys->p_spu, psz_string );
    }
    free( psz_string );

    /* OSD menu transcoding parameters */
    p_sys->psz_osdenc = NULL;
    p_sys->p_osd_cfg  = NULL;
    p_sys->i_osdcodec = 0;
    p_sys->b_osd   = var_GetBool( p_stream, SOUT_CFG_PREFIX "osd" );

    if( p_sys->b_osd )
    {
        char *psz_next;

        psz_next = config_ChainCreate( &p_sys->psz_osdenc,
                                   &p_sys->p_osd_cfg, strdup( "dvbsub") );
        free( psz_next );

        p_sys->i_osdcodec = VLC_CODEC_YUVP;

        msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );

        if( !p_sys->p_spu )
        {
            p_sys->p_spu = spu_Create( p_stream );
            if( p_sys->p_spu )
                spu_ChangeSources( p_sys->p_spu, "osdmenu" );
        }
        else
        {
            spu_ChangeSources( p_sys->p_spu, "osdmenu" );
        }
    }

    /* Audio settings */
    p_sys->b_master_sync = var_GetBool( p_stream, SOUT_CFG_PREFIX "audio-sync" );
    if( p_sys->f_fps > 0 ) p_sys->b_master_sync = true;

    p_stream->pf_add    = Add;
    p_stream->pf_del    = Del;
    p_stream->pf_send   = Send;
    p_stream->p_sys     = p_sys;

    return VLC_SUCCESS;
}
Ejemplo n.º 5
0
/*****************************************************************************
 * 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;
    char              *psz_string;

    if( !p_stream->p_next )
    {
        msg_Err( p_stream, "cannot create chain" );
        return VLC_EGENERIC;
    }
    p_sys = calloc( 1, sizeof( *p_sys ) );
    p_sys->i_master_drift = 0;

    config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
                   p_stream->p_cfg );

    /* Audio transcoding parameters */
    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "aenc" );
    p_sys->psz_aenc = NULL;
    p_sys->p_audio_cfg = NULL;
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
                                       psz_string );
        free( psz_next );
    }
    free( psz_string );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "acodec" );
    p_sys->i_acodec = 0;
    if( psz_string && *psz_string )
    {
        char fcc[5] = "    \0";
        memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
        p_sys->i_acodec = vlc_fourcc_GetCodecFromString( AUDIO_ES, fcc );
        msg_Dbg( p_stream, "Checking codec mapping for %s got %4.4s ", fcc, (char*)&p_sys->i_acodec);
    }
    free( psz_string );

    p_sys->psz_alang = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "alang" );

    p_sys->i_abitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ab" );
    if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;

    p_sys->i_sample_rate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "samplerate" );

    p_sys->i_channels = var_GetInteger( p_stream, SOUT_CFG_PREFIX "channels" );

    if( p_sys->i_acodec )
    {
        if( ( p_sys->i_acodec == VLC_CODEC_MP3 ||
              p_sys->i_acodec == VLC_CODEC_MP2 ||
              p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 )
        {
            msg_Warn( p_stream, "%d channels invalid for mp2/mp3, forcing to 2",
                      p_sys->i_channels );
            p_sys->i_channels = 2;
        }
        msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
                 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
                 p_sys->i_channels, p_sys->i_abitrate / 1000 );
    }

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "afilter" );
    if( psz_string && *psz_string )
        p_sys->psz_af = strdup( psz_string );
    else
        p_sys->psz_af = NULL;
    free( psz_string );

    /* Video transcoding parameters */
    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "venc" );
    p_sys->psz_venc = NULL;
    p_sys->p_video_cfg = NULL;
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
                                   psz_string );
        free( psz_next );
    }
    free( psz_string );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vcodec" );
    p_sys->i_vcodec = 0;
    if( psz_string && *psz_string )
    {
        char fcc[5] = "    \0";
        memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
        p_sys->i_vcodec = vlc_fourcc_GetCodecFromString( VIDEO_ES, fcc );
        msg_Dbg( p_stream, "Checking video codec mapping for %s got %4.4s ", fcc, (char*)&p_sys->i_vcodec);
    }
    free( psz_string );

    p_sys->i_vbitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "vb" );
    if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;

    p_sys->f_scale = var_GetFloat( p_stream, SOUT_CFG_PREFIX "scale" );

    p_sys->b_master_sync = var_InheritURational( p_stream, &p_sys->fps_num, &p_sys->fps_den, SOUT_CFG_PREFIX "fps" ) == VLC_SUCCESS;

    p_sys->i_width = var_GetInteger( p_stream, SOUT_CFG_PREFIX "width" );

    p_sys->i_height = var_GetInteger( p_stream, SOUT_CFG_PREFIX "height" );

    p_sys->i_maxwidth = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxwidth" );

    p_sys->i_maxheight = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxheight" );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vfilter" );
    if( psz_string && *psz_string )
        p_sys->psz_vf2 = strdup(psz_string );
    else
        p_sys->psz_vf2 = NULL;
    free( psz_string );

    p_sys->b_deinterlace = var_GetBool( p_stream, SOUT_CFG_PREFIX "deinterlace" );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "deinterlace-module" );
    p_sys->psz_deinterlace = NULL;
    p_sys->p_deinterlace_cfg = NULL;
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
                                   &p_sys->p_deinterlace_cfg,
                                   psz_string );
        free( psz_next );
    }
    free( psz_string );

    p_sys->i_threads = var_GetInteger( p_stream, SOUT_CFG_PREFIX "threads" );
    p_sys->b_high_priority = var_GetBool( p_stream, SOUT_CFG_PREFIX "high-priority" );

    if( p_sys->i_vcodec )
    {
        msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
                 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
                 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
    }

    /* Disable hardware decoding by default (unlike normal playback) */
    psz_string = var_CreateGetString( p_stream, "avcodec-hw" );
    if( !strcasecmp( "any", psz_string ) )
        var_SetString( p_stream, "avcodec-hw", "none" );
    free( psz_string );

    /* Subpictures transcoding parameters */
    p_sys->p_spu = NULL;
    p_sys->p_spu_blend = NULL;
    p_sys->psz_senc = NULL;
    p_sys->p_spu_cfg = NULL;
    p_sys->i_scodec = 0;

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "senc" );
    if( psz_string && *psz_string )
    {
        char *psz_next;
        psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
                                   psz_string );
        free( psz_next );
    }
    free( psz_string );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "scodec" );
    if( psz_string && *psz_string )
    {
        char fcc[5] = "    \0";
        memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
        p_sys->i_scodec = vlc_fourcc_GetCodecFromString( SPU_ES, fcc );
        msg_Dbg( p_stream, "Checking spu codec mapping for %s got %4.4s ", fcc, (char*)&p_sys->i_scodec);
    }
    free( psz_string );

    if( p_sys->i_scodec )
    {
        msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
    }

    p_sys->b_soverlay = var_GetBool( p_stream, SOUT_CFG_PREFIX "soverlay" );

    psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "sfilter" );
    if( psz_string && *psz_string )
    {
        p_sys->p_spu = spu_Create( p_stream );
        if( p_sys->p_spu )
            spu_ChangeSources( p_sys->p_spu, psz_string );
    }
    free( psz_string );

    /* OSD menu transcoding parameters */
    p_sys->psz_osdenc = NULL;
    p_sys->p_osd_cfg  = NULL;
    p_sys->i_osdcodec = 0;
    p_sys->b_osd   = var_GetBool( p_stream, SOUT_CFG_PREFIX "osd" );

    if( p_sys->b_osd )
    {
        char *psz_next;

        psz_next = config_ChainCreate( &p_sys->psz_osdenc,
                                   &p_sys->p_osd_cfg, "dvbsub" );
        free( psz_next );

        p_sys->i_osdcodec = VLC_CODEC_YUVP;

        msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );

        if( !p_sys->p_spu )
        {
            p_sys->p_spu = spu_Create( p_stream );
            if( p_sys->p_spu )
                spu_ChangeSources( p_sys->p_spu, "osdmenu" );
        }
        else
        {
            spu_ChangeSources( p_sys->p_spu, "osdmenu" );
        }
    }

    p_stream->pf_add    = Add;
    p_stream->pf_del    = Del;
    p_stream->pf_send   = Send;
    p_stream->p_sys     = p_sys;

    return VLC_SUCCESS;
}