Ejemplo n.º 1
0
Archivo: chain.c Proyecto: mstorsjo/vlc
static int CreateResizeChromaChain( filter_t *p_parent, const es_format_t *p_fmt_mid )
{
    filter_sys_t *p_sys = p_parent->p_sys;
    filter_chain_Reset( p_sys->p_chain, &p_parent->fmt_in, &p_parent->fmt_out );

    int i_ret = filter_chain_AppendConverter( p_sys->p_chain,
                                              NULL, p_fmt_mid );
    if( i_ret != VLC_SUCCESS )
        return i_ret;

    if( p_parent->b_allow_fmt_out_change )
    {
        /* XXX: Update i_sar_num/i_sar_den from last converter. Cf.
         * p_filter->b_allow_fmt_out_change comment in video_chroma/swscale.c.
         * */

        es_format_t fmt_out;
        es_format_Copy( &fmt_out,
                        filter_chain_GetFmtOut( p_sys->p_chain ) );
        fmt_out.video.i_chroma = p_parent->fmt_out.video.i_chroma;

        i_ret = filter_chain_AppendConverter( p_sys->p_chain,
                                              NULL, &fmt_out );
        es_format_Clean( &fmt_out );
    }
    else
        i_ret = filter_chain_AppendConverter( p_sys->p_chain,
                                              NULL, &p_parent->fmt_out );

    if( i_ret != VLC_SUCCESS )
        filter_chain_Reset( p_sys->p_chain, NULL, NULL );
    return i_ret;
}
Ejemplo n.º 2
0
/*****************************************************************************
 * Builders
 *****************************************************************************/
static int BuildChromaResize( filter_t *p_filter )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    es_format_t fmt_mid;
    int i_ret;

    /* Lets try resizing and then doing the chroma conversion */
    filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out );

    msg_Dbg( p_filter, "Trying to build resize+chroma" );
    EsFormatMergeSize( &fmt_mid, &p_filter->fmt_in, &p_filter->fmt_out );
    i_ret = CreateChain( p_sys->p_chain, &fmt_mid, NULL );
    es_format_Clean( &fmt_mid );
    if( i_ret == VLC_SUCCESS )
        return VLC_SUCCESS;

    /* Lets try it the other way arround (chroma and then resize) */
    filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out );

    msg_Dbg( p_filter, "Trying to build chroma+resize" );
    EsFormatMergeSize( &fmt_mid, &p_filter->fmt_out, &p_filter->fmt_in );
    i_ret = CreateChain( p_sys->p_chain, &fmt_mid, NULL );
    es_format_Clean( &fmt_mid );
    if( i_ret == VLC_SUCCESS )
        return VLC_SUCCESS;

    return VLC_EGENERIC;
}
Ejemplo n.º 3
0
Archivo: chain.c Proyecto: mstorsjo/vlc
static int BuildFilterChain( filter_t *p_filter )
{
    es_format_t fmt_mid;
    int i_ret = VLC_EGENERIC;

    filter_sys_t *p_sys = p_filter->p_sys;

    /* Now try chroma format list */
    const vlc_fourcc_t *pi_allowed_chromas = get_allowed_chromas( p_filter );
    for( int i = 0; pi_allowed_chromas[i]; i++ )
    {
        filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out );

        const vlc_fourcc_t i_chroma = pi_allowed_chromas[i];
        if( i_chroma == p_filter->fmt_in.i_codec ||
            i_chroma == p_filter->fmt_out.i_codec )
            continue;

        msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man",
                 (char*)&i_chroma );

        es_format_Copy( &fmt_mid, &p_filter->fmt_in );
        fmt_mid.i_codec        =
        fmt_mid.video.i_chroma = i_chroma;
        fmt_mid.video.i_rmask  = 0;
        fmt_mid.video.i_gmask  = 0;
        fmt_mid.video.i_bmask  = 0;
        video_format_FixRgb(&fmt_mid.video);

        if( filter_chain_AppendConverter( p_sys->p_chain,
                                          NULL, &fmt_mid ) == VLC_SUCCESS )
        {
            p_sys->p_video_filter =
                filter_chain_AppendFilter( p_sys->p_chain,
                                           p_filter->psz_name, p_filter->p_cfg,
                                           &fmt_mid, &fmt_mid );
            if( p_sys->p_video_filter )
            {
                filter_AddProxyCallbacks( p_filter,
                                          p_sys->p_video_filter,
                                          RestartFilterCallback );
                if (p_sys->p_video_filter->pf_video_mouse != NULL)
                    p_filter->pf_video_mouse = ChainMouse;
                es_format_Clean( &fmt_mid );
                i_ret = VLC_SUCCESS;
                break;
            }
        }
        es_format_Clean( &fmt_mid );
    }
    if( i_ret != VLC_SUCCESS )
        filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out );

    return i_ret;
}
Ejemplo n.º 4
0
static void transcode_video_filter_init( sout_stream_t *p_stream,
                                         sout_stream_id_t *id )
{
    es_format_t *p_fmt_out = &id->p_decoder->fmt_out;
    id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;

    id->p_f_chain = filter_chain_New( p_stream, "video filter2",
                                      false,
                                      transcode_video_filter_allocation_init,
                                      transcode_video_filter_allocation_clear,
                                      p_stream->p_sys );
    filter_chain_Reset( id->p_f_chain, p_fmt_out, p_fmt_out );

    /* Deinterlace */
    if( p_stream->p_sys->b_deinterlace )
    {
        filter_chain_AppendFilter( id->p_f_chain,
                                   p_stream->p_sys->psz_deinterlace,
                                   p_stream->p_sys->p_deinterlace_cfg,
                                   &id->p_decoder->fmt_out,
                                   &id->p_decoder->fmt_out );

        p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain );
    }

    /* Check that we have visible_width/height*/
    if( !p_fmt_out->video.i_visible_height )
        p_fmt_out->video.i_visible_height = p_fmt_out->video.i_height;
    if( !p_fmt_out->video.i_visible_width )
        p_fmt_out->video.i_visible_width = p_fmt_out->video.i_width;

    if( p_stream->p_sys->psz_vf2 )
    {
        id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
                                          true,
                           transcode_video_filter_allocation_init,
                           transcode_video_filter_allocation_clear,
                           p_stream->p_sys );
        filter_chain_Reset( id->p_uf_chain, p_fmt_out,
                            &id->p_encoder->fmt_in );
        filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 );
        p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
        es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
        id->p_encoder->fmt_out.video.i_width =
            id->p_encoder->fmt_in.video.i_width;
        id->p_encoder->fmt_out.video.i_height =
            id->p_encoder->fmt_in.video.i_height;
        id->p_encoder->fmt_out.video.i_sar_num =
            id->p_encoder->fmt_in.video.i_sar_num;
        id->p_encoder->fmt_out.video.i_sar_den =
            id->p_encoder->fmt_in.video.i_sar_den;
    }

}
Ejemplo n.º 5
0
/**
 * Filter chain destruction
 */
void filter_chain_Delete( filter_chain_t *p_chain )
{
    filter_chain_Reset( p_chain, NULL, NULL );

    es_format_Clean( &p_chain->fmt_in );
    es_format_Clean( &p_chain->fmt_out );

    free( p_chain );
}
Ejemplo n.º 6
0
static void transcode_video_filter_init( sout_stream_t *p_stream,
                                         sout_stream_id_t *id )
{

    id->p_f_chain = filter_chain_New( p_stream, "video filter2",
                                     false,
                                     transcode_video_filter_allocation_init,
                                     transcode_video_filter_allocation_clear,
                                     p_stream->p_sys );
    /* Deinterlace */
    if( p_stream->p_sys->b_deinterlace )
    {
       filter_chain_AppendFilter( id->p_f_chain,
                                  p_stream->p_sys->psz_deinterlace,
                                  p_stream->p_sys->p_deinterlace_cfg,
                                  &id->p_decoder->fmt_out,
                                  &id->p_decoder->fmt_out );
    }

    /* Take care of the scaling and chroma conversions */
    if( ( id->p_decoder->fmt_out.video.i_chroma !=
          id->p_encoder->fmt_in.video.i_chroma ) ||
        ( id->p_decoder->fmt_out.video.i_width !=
          id->p_encoder->fmt_in.video.i_width ) ||
        ( id->p_decoder->fmt_out.video.i_height !=
          id->p_encoder->fmt_in.video.i_height ) )
    {
       filter_chain_AppendFilter( id->p_f_chain,
                                  NULL, NULL,
                                  &id->p_decoder->fmt_out,
                                  &id->p_encoder->fmt_in );
    }

    if( p_stream->p_sys->psz_vf2 )
    {
        const es_format_t *p_fmt_out;
        id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
                                          true,
                           transcode_video_filter_allocation_init,
                           transcode_video_filter_allocation_clear,
                           p_stream->p_sys );
        filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
                            &id->p_encoder->fmt_in );
        filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 );
        p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
        es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
        id->p_encoder->fmt_out.video.i_width =
            id->p_encoder->fmt_in.video.i_width;
        id->p_encoder->fmt_out.video.i_height =
            id->p_encoder->fmt_in.video.i_height;
        id->p_encoder->fmt_out.video.i_sar_num =
            id->p_encoder->fmt_in.video.i_sar_num;
        id->p_encoder->fmt_out.video.i_sar_den =
            id->p_encoder->fmt_in.video.i_sar_den;
    }

}
Ejemplo n.º 7
0
Archivo: chain.c Proyecto: mstorsjo/vlc
static int CreateChain( filter_t *p_parent, const es_format_t *p_fmt_mid )
{
    filter_sys_t *p_sys = p_parent->p_sys;
    filter_chain_Reset( p_sys->p_chain, &p_parent->fmt_in, &p_parent->fmt_out );

    filter_t *p_filter;

    if( p_parent->fmt_in.video.orientation != p_fmt_mid->video.orientation)
    {
        p_filter = AppendTransform( p_sys->p_chain, &p_parent->fmt_in, p_fmt_mid );
        // Check if filter was enough:
        if( p_filter == NULL )
            return VLC_EGENERIC;
        if( es_format_IsSimilar(&p_filter->fmt_out, &p_parent->fmt_out ))
           return VLC_SUCCESS;
    }
    else
    {
        if( filter_chain_AppendConverter( p_sys->p_chain,
                                          NULL, p_fmt_mid ) )
            return VLC_EGENERIC;
    }

    if( p_fmt_mid->video.orientation != p_parent->fmt_out.video.orientation)
    {
        if( AppendTransform( p_sys->p_chain, p_fmt_mid,
                             &p_parent->fmt_out ) == NULL )
            goto error;
    }
    else
    {
        if( filter_chain_AppendConverter( p_sys->p_chain,
                                          p_fmt_mid, &p_parent->fmt_out ) )
            goto error;
    }
    return VLC_SUCCESS;
error:
    //Clean up.
    filter_chain_Reset( p_sys->p_chain, NULL, NULL );
    return VLC_EGENERIC;
}
Ejemplo n.º 8
0
static int CreateChain( filter_t *p_parent, es_format_t *p_fmt_mid, config_chain_t *p_cfg )
{
    filter_chain_Reset( p_parent->p_sys->p_chain, &p_parent->fmt_in, &p_parent->fmt_out );

    filter_t *p_filter;

    if( p_parent->fmt_in.video.orientation != p_fmt_mid->video.orientation)
    {
        p_filter = AppendTransform( p_parent->p_sys->p_chain, &p_parent->fmt_in, p_fmt_mid );
    }
    else
    {
        p_filter = filter_chain_AppendFilter( p_parent->p_sys->p_chain, NULL, p_cfg, NULL, p_fmt_mid );
    }

    if( !p_filter )
        return VLC_EGENERIC;

    //Check if first filter was enough (transform filter most likely):
    if( es_format_IsSimilar(&p_filter->fmt_out, &p_parent->fmt_out ))
        return VLC_SUCCESS;

    if( p_fmt_mid->video.orientation != p_parent->fmt_out.video.orientation)
    {
        p_filter = AppendTransform( p_parent->p_sys->p_chain, p_fmt_mid, &p_parent->fmt_out );
    }
    else
    {
        p_filter = filter_chain_AppendFilter( p_parent->p_sys->p_chain, NULL, p_cfg, p_fmt_mid, NULL );
    }

    if( !p_filter )
    {
        //Clean up.
        filter_chain_Reset( p_parent->p_sys->p_chain, NULL, NULL );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Ejemplo n.º 9
0
static sout_stream_id_sys_t * Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    bridge_t *p_bridge;
    bridged_es_t *p_es;
    char *psz_chain;
    int i;

    if( p_sys->b_inited || p_fmt->i_cat != VIDEO_ES )
        return NULL;

    /* Create decoder object */
    p_sys->p_decoder = vlc_object_create( p_stream, sizeof( decoder_t ) );
    if( !p_sys->p_decoder )
        return NULL;
    p_sys->p_decoder->p_module = NULL;
    p_sys->p_decoder->fmt_in = *p_fmt;
    p_sys->p_decoder->b_frame_drop_allowed = true;
    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_format_update = video_update_format_decoder;
    p_sys->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
    p_sys->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
    if( !p_sys->p_decoder->p_owner )
    {
        vlc_object_release( p_sys->p_decoder );
        return NULL;
    }

    p_sys->p_decoder->p_owner->video = p_fmt->video;
    //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", false );

    if( !p_sys->p_decoder->p_module || !p_sys->p_decoder->pf_decode_video )
    {
        if( p_sys->p_decoder->p_module )
        {
            msg_Err( p_stream, "instanciated a non video decoder" );
            module_unneed( p_sys->p_decoder, p_sys->p_decoder->p_module );
        }
        else
        {
            msg_Err( p_stream, "cannot find decoder" );
        }
        free( p_sys->p_decoder->p_owner );
        vlc_object_release( p_sys->p_decoder );
        return NULL;
    }

    p_sys->b_inited = true;
    vlc_global_lock( VLC_MOSAIC_MUTEX );

    p_bridge = GetBridge( p_stream );
    if ( p_bridge == NULL )
    {
        vlc_object_t *p_libvlc = VLC_OBJECT( p_stream->obj.libvlc );
        vlc_value_t val;

        p_bridge = xmalloc( 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 = xrealloc( p_bridge->pp_es,
                          (p_bridge->i_es_num + 1) * sizeof(bridged_es_t *) );
        p_bridge->i_es_num++;
        p_bridge->pp_es[i] = xmalloc( sizeof(bridged_es_t) );
    }

    p_sys->p_es = p_es = p_bridge->pp_es[i];

    p_es->i_alpha = var_GetInteger( p_stream, CFG_PREFIX "alpha" );
    p_es->i_x = var_GetInteger( p_stream, CFG_PREFIX "x" );
    p_es->i_y = var_GetInteger( p_stream, CFG_PREFIX "y" );

    //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 = false;

    vlc_global_unlock( VLC_MOSAIC_MUTEX );

    if ( p_sys->i_height || p_sys->i_width )
    {
        p_sys->p_image = image_HandlerCreate( p_stream );
    }
    else
    {
        p_sys->p_image = NULL;
    }

    msg_Dbg( p_stream, "mosaic bridge id=%s pos=%d", p_es->psz_id, i );

    /* Create user specified video filters */
    psz_chain = var_GetNonEmptyString( p_stream, CFG_PREFIX "vfilter" );
    msg_Dbg( p_stream, "psz_chain: %s", psz_chain );
    if( psz_chain )
    {
        filter_owner_t owner = {
            .sys = p_sys->p_decoder->p_owner,
            .video = {
                .buffer_new = video_new_buffer_filter,
            },
        };

        p_sys->p_vf2 = filter_chain_NewVideo( p_stream, false, &owner );
        es_format_t fmt;
        es_format_Copy( &fmt, &p_sys->p_decoder->fmt_out );
        if( p_sys->i_chroma )
            fmt.video.i_chroma = p_sys->i_chroma;
        filter_chain_Reset( p_sys->p_vf2, &fmt, &fmt );
        filter_chain_AppendFromString( p_sys->p_vf2, psz_chain );
        free( psz_chain );
    }
    else
    {
Ejemplo n.º 10
0
int transcode_audio_new( sout_stream_t *p_stream,
                                sout_stream_id_t *id )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    es_format_t fmt_last;

    /*
     * Open decoder
     */

    /* Initialization of decoder structures */
    id->p_decoder->fmt_out = id->p_decoder->fmt_in;
    id->p_decoder->fmt_out.i_extra = 0;
    id->p_decoder->fmt_out.p_extra = 0;
    id->p_decoder->pf_decode_audio = NULL;
    id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
    id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
    /* id->p_decoder->p_cfg = p_sys->p_audio_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 audio decoder" );
        return VLC_EGENERIC;
    }
    id->p_decoder->fmt_out.audio.i_bitspersample =
        aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
    fmt_last = id->p_decoder->fmt_out;
    /* Fix AAC SBR changing number of channels and sampling rate */
    if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
        fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
        fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
        fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;

    /*
     * 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_out.i_codec );
    id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;

    id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
    id->p_encoder->fmt_in.audio.i_physical_channels =
        id->p_encoder->fmt_out.audio.i_physical_channels;
    id->p_encoder->fmt_in.audio.i_original_channels =
        id->p_encoder->fmt_out.audio.i_original_channels;
    id->p_encoder->fmt_in.audio.i_channels =
        id->p_encoder->fmt_out.audio.i_channels;
    id->p_encoder->fmt_in.audio.i_bitspersample =
        aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );

    id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
    id->p_encoder->p_module =
        module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
    if( !id->p_encoder->p_module )
    {
        msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)",
                 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
                 (char *)&p_sys->i_acodec );
        module_unneed( id->p_decoder, id->p_decoder->p_module );
        id->p_decoder->p_module = NULL;
        return VLC_EGENERIC;
    }
    id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
    id->p_encoder->fmt_in.audio.i_bitspersample =
        aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );

    /* Load user specified audio filters */
    if( p_sys->psz_af )
    {
        es_format_t fmt_fl32 = fmt_last;
        fmt_fl32.i_codec =
        fmt_fl32.audio.i_format = VLC_CODEC_FL32;
        id->p_uf_chain = filter_chain_New( p_stream, "audio filter", false,
                                           transcode_audio_filter_allocation_init, NULL, NULL );
        filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );

        if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
                                                &fmt_fl32, &fmt_last ) )
        {
            transcode_audio_close( id );
            return VLC_EGENERIC;
        }
        fmt_last = fmt_fl32;

        if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af ) > 0 )
            fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
    }

    /* Load conversion filters */
    id->p_f_chain = filter_chain_New( p_stream, "audio filter", true,
                    transcode_audio_filter_allocation_init, NULL, NULL );
    filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );

    if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
                                            &id->p_encoder->fmt_in, &fmt_last ) )
    {
        transcode_audio_close( id );
        return VLC_EGENERIC;
    }
    fmt_last = id->p_encoder->fmt_in;

    /* */
    id->p_encoder->fmt_out.i_codec =
        vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );

    return VLC_SUCCESS;
}
Ejemplo n.º 11
0
static int BuildChromaChain( filter_t *p_filter )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    es_format_t fmt_mid;

    /* We have to protect ourself against a too high recursion */
    const char *psz_option = MODULE_STRING"-level";
    int i_level = 0;
    for( const config_chain_t *c = p_filter->p_cfg; c != NULL; c = c->p_next)
    {
        if( c->psz_name && c->psz_value && !strcmp(c->psz_name, psz_option) )
        {
            i_level = atoi(c->psz_value);
            if( i_level < 0 || i_level > CHAIN_LEVEL_MAX )
            {
                msg_Err( p_filter, "Too high level of recursion (%d)", i_level );
                return VLC_EGENERIC;
            }
            break;
        }
    }

    /* */
    int i_ret = VLC_EGENERIC;

    /* */
    config_chain_t cfg_level;
    memset(&cfg_level, 0, sizeof(cfg_level));
    cfg_level.psz_name = strdup(psz_option);
    if( asprintf( &cfg_level.psz_value, "%d", i_level + 1) < 0 )
        cfg_level.psz_value = NULL;
    if( !cfg_level.psz_name || !cfg_level.psz_value )
        goto exit;

    /* Now try chroma format list */
    for( int i = 0; pi_allowed_chromas[i]; i++ )
    {
        const vlc_fourcc_t i_chroma = pi_allowed_chromas[i];
        if( i_chroma == p_filter->fmt_in.i_codec ||
            i_chroma == p_filter->fmt_out.i_codec )
            continue;

        msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man",
                 (char*)&i_chroma );

        es_format_Copy( &fmt_mid, &p_filter->fmt_in );
        fmt_mid.i_codec        =
        fmt_mid.video.i_chroma = i_chroma;
        fmt_mid.video.i_rmask  = 0;
        fmt_mid.video.i_gmask  = 0;
        fmt_mid.video.i_bmask  = 0;
        video_format_FixRgb(&fmt_mid.video);

        filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out );

        i_ret = CreateChain( p_sys->p_chain, &fmt_mid, &cfg_level );
        es_format_Clean( &fmt_mid );

        if( i_ret == VLC_SUCCESS )
            break;
    }

exit:
    free( cfg_level.psz_name );
    free( cfg_level.psz_value );
    return i_ret;
}
Ejemplo n.º 12
0
static int Activate( vlc_object_t *p_this )
{
    filter_t *p_filter = (filter_t *)p_this;
    unsigned i_canvas_width; /* width of output canvas */
    unsigned i_canvas_height; /* height of output canvas */
    unsigned i_canvas_aspect; /* canvas PictureAspectRatio */
    es_format_t fmt; /* target format after up/down conversion */
    char psz_croppadd[100];
    int i_padd,i_offset;
    char *psz_aspect, *psz_parser;
    bool b_padd;
    unsigned i_fmt_in_aspect;

    if( !p_filter->b_allow_fmt_out_change )
    {
        msg_Err( p_filter, "Picture format change isn't allowed" );
        return VLC_EGENERIC;
    }

    if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
    {
        msg_Err( p_filter, "Input and output chromas don't match" );
        return VLC_EGENERIC;
    }

    config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
                       p_filter->p_cfg );

    i_canvas_width = var_CreateGetInteger( p_filter, CFG_PREFIX "width" );
    i_canvas_height = var_CreateGetInteger( p_filter, CFG_PREFIX "height" );

    if( i_canvas_width == 0 || i_canvas_height == 0 )
    {
        msg_Err( p_filter, "Width and height options must be set" );
        return VLC_EGENERIC;
    }

    if( i_canvas_width & 1 || i_canvas_height & 1 )
    {
        /* If this restriction were ever relaxed, it is very important to
         * get the field polatiry correct */
        msg_Err( p_filter, "Width and height options must be even integers" );
        return VLC_EGENERIC;
    }

    i_fmt_in_aspect = (int64_t)p_filter->fmt_in.video.i_sar_num *
                      p_filter->fmt_in.video.i_width *
                      VOUT_ASPECT_FACTOR /
                      p_filter->fmt_in.video.i_sar_den /
                      p_filter->fmt_in.video.i_height;
    psz_aspect = var_CreateGetNonEmptyString( p_filter, CFG_PREFIX "aspect" );
    if( psz_aspect )
    {
        psz_parser = strchr( psz_aspect, ':' );
        int numerator = atoi( psz_aspect );
        int denominator = psz_parser ? atoi( psz_parser+1 ) : 0;
        denominator = denominator == 0 ? 1 : denominator;
        i_canvas_aspect = numerator * VOUT_ASPECT_FACTOR / denominator;
        free( psz_aspect );

        if( numerator <= 0 || denominator < 0 )
        {
            msg_Err( p_filter, "Aspect ratio must be strictly positive" );
            return VLC_EGENERIC;
        }
    }
    else
    {
        /* if there is no user supplied aspect ratio, assume the canvas
         * has the same sample aspect ratio as the subpicture */
        /* aspect = subpic_sar * canvas_width / canvas_height
         *  where subpic_sar = subpic_ph * subpic_par / subpic_pw */
        i_canvas_aspect = (uint64_t) p_filter->fmt_in.video.i_height
                        * i_fmt_in_aspect
                        * i_canvas_width
                        / (i_canvas_height * p_filter->fmt_in.video.i_width);
    }

    b_padd = var_CreateGetBool( p_filter, CFG_PREFIX "padd" );

    filter_sys_t *p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;
    p_filter->p_sys = p_sys;

    p_sys->p_chain = filter_chain_New( p_filter, "video filter2", true,
                                       alloc_init, NULL, p_filter );
    if( !p_sys->p_chain )
    {
        msg_Err( p_filter, "Could not allocate filter chain" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    es_format_Copy( &fmt, &p_filter->fmt_in );

    /* one dimension will end up with one of the following: */
    fmt.video.i_width = i_canvas_width;
    fmt.video.i_height = i_canvas_height;

    if( b_padd )
    {
        /* Padd */
        if( i_canvas_aspect > i_fmt_in_aspect )
        {
            /* The canvas has a wider aspect than the subpicture:
             *  ie, pillarbox the [scaled] subpicture */
            /* The following is derived form:
             * width = upconverted_subpic_height * subpic_par / canvas_sar
             *  where canvas_sar = canvas_width / (canvas_height * canvas_par)
             * then simplify */
            fmt.video.i_width = i_canvas_width
                              * i_fmt_in_aspect
                              / i_canvas_aspect;
            if( fmt.video.i_width & 1 ) fmt.video.i_width -= 1;

            i_padd = (i_canvas_width - fmt.video.i_width) / 2;
            i_offset = (i_padd & 1);
            _snprintf( psz_croppadd, 100, "croppadd{paddleft=%d,paddright=%d}",
                      i_padd - i_offset, i_padd + i_offset );			// sunqueen modify
        }
        else
        {
            /* The canvas has a taller aspect than the subpicture:
             *  ie, letterbox the [scaled] subpicture */
            fmt.video.i_height = i_canvas_height
                               * i_canvas_aspect
                               / i_fmt_in_aspect;
            if( fmt.video.i_height & 1 ) fmt.video.i_height -= 1;

            i_padd = (i_canvas_height - fmt.video.i_height ) / 2;
            i_offset = (i_padd & 1);
            _snprintf( psz_croppadd, 100, "croppadd{paddtop=%d,paddbottom=%d}",
                      i_padd - i_offset, i_padd + i_offset );			// sunqueen modify
        }
    }
    else
    {
        /* Crop */
        if( i_canvas_aspect < i_fmt_in_aspect )
        {
            /* The canvas has a narrower aspect than the subpicture:
             *  ie, crop the [scaled] subpicture horizontally */
            fmt.video.i_width = i_canvas_width
                              * i_fmt_in_aspect
                              / i_canvas_aspect;
            if( fmt.video.i_width & 1 ) fmt.video.i_width -= 1;

            i_padd = (fmt.video.i_width - i_canvas_width) / 2;
            i_offset = (i_padd & 1);
            _snprintf( psz_croppadd, 100, "croppadd{cropleft=%d,cropright=%d}",
                      i_padd - i_offset, i_padd + i_offset );			// sunqueen modify
        }
        else
        {
            /* The canvas has a shorter aspect than the subpicture:
             *  ie, crop the [scaled] subpicture vertically */
            fmt.video.i_height = i_canvas_height
                               * i_canvas_aspect
                               / i_fmt_in_aspect;
            if( fmt.video.i_height & 1 ) fmt.video.i_height -= 1;

            i_padd = (fmt.video.i_height - i_canvas_height) / 2;
            i_offset = (i_padd & 1);
            _snprintf( psz_croppadd, 100, "croppadd{croptop=%d,cropbottom=%d}",
                      i_padd - i_offset, i_padd + i_offset );			// sunqueen modify
        }
    }

    /* xxx, should the clean area include the letter-boxing?
     *  probably not, as some codecs can make use of that information
     *  and it should be a scaled version of the input clean area
     *   -- davidf */
    fmt.video.i_visible_width = fmt.video.i_width;
    fmt.video.i_visible_height = fmt.video.i_height;

    filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &fmt );
    /* Append scaling module */
    filter_chain_AppendFilter( p_sys->p_chain, NULL, NULL, NULL, NULL );
    /* Append padding module */
    filter_chain_AppendFromString( p_sys->p_chain, psz_croppadd );

    fmt = *filter_chain_GetFmtOut( p_sys->p_chain );
    es_format_Copy( &p_filter->fmt_out, &fmt );

    p_filter->fmt_out.video.i_sar_num =
        i_canvas_aspect    * p_filter->fmt_out.video.i_height;
    p_filter->fmt_out.video.i_sar_den =
        VOUT_ASPECT_FACTOR * p_filter->fmt_out.video.i_width;

    if( p_filter->fmt_out.video.i_width != i_canvas_width
     || p_filter->fmt_out.video.i_height != i_canvas_height )
    {
        msg_Warn( p_filter, "Looks like something went wrong. "
                  "Output size is %dx%d while we asked for %dx%d",
                  p_filter->fmt_out.video.i_width,
                  p_filter->fmt_out.video.i_height,
                  i_canvas_width, i_canvas_height );
    }

    p_filter->pf_video_filter = Filter;

    return VLC_SUCCESS;
}