int libavsmash_video_initialize_decoder_configuration
(
    libavsmash_video_decode_handler_t *vdhp,
    AVFormatContext                   *format_ctx,
    int                                threads
)
{
    char error_string[128] = { 0 };
    if( libavsmash_video_get_summaries( vdhp ) < 0 )
        return -1;
    /* libavformat */
    uint32_t type = AVMEDIA_TYPE_VIDEO;
    uint32_t i;
    for( i = 0; i < format_ctx->nb_streams && format_ctx->streams[i]->codecpar->codec_type != type; i++ );
    if( i == format_ctx->nb_streams )
    {
        strcpy( error_string, "Failed to find stream by libavformat.\n" );
        goto fail;
    }
    /* libavcodec */
    AVCodecParameters *codecpar = format_ctx->streams[i]->codecpar;
    if( libavsmash_find_and_open_decoder( &vdhp->config, codecpar, threads, 1 ) < 0 )
    {
        strcpy( error_string, "Failed to find and open the video decoder.\n" );
        goto fail;
    }
    return initialize_decoder_configuration( vdhp->root, vdhp->track_id, &vdhp->config );
fail:;
    lw_log_handler_t *lhp = libavsmash_video_get_log_handler( vdhp );
    lw_log_show( lhp, LW_LOG_FATAL, "%s", error_string );
    return -1;
}
static const VSFrameRef *VS_CC vs_filter_get_frame( int n, int activation_reason, void **instance_data, void **frame_data, VSFrameContext *frame_ctx, VSCore *core, const VSAPI *vsapi )
{
    if( activation_reason != arInitial )
        return NULL;
    lsmas_handler_t *hp = (lsmas_handler_t *)*instance_data;
    VSVideoInfo     *vi = &hp->vi;
    uint32_t sample_number = MIN( n + 1, vi->numFrames );   /* For L-SMASH, sample_number is 1-origin. */
    libavsmash_video_decode_handler_t *vdhp = hp->vdhp;
    libavsmash_video_output_handler_t *vohp = hp->vohp;
    if( libavsmash_video_get_error( vdhp ) )
    {
        vsapi->setFilterError( "lsmas: failed to output a video frame.", frame_ctx );
        return NULL;
    }
    /* Set up VapourSynth error handler. */
    vs_basic_handler_t vsbh = { 0 };
    vsbh.out       = NULL;
    vsbh.frame_ctx = frame_ctx;
    vsbh.vsapi     = vsapi;
    lw_log_handler_t *lhp = libavsmash_video_get_log_handler( vdhp );
    lhp->priv     = &vsbh;
    lhp->show_log = set_error;
    /* Get and decode the desired video frame. */
    vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)vohp->private_handler;
    vs_vohp->frame_ctx = frame_ctx;
    vs_vohp->core      = core;
    vs_vohp->vsapi     = vsapi;
    if( libavsmash_video_get_frame( vdhp, vohp, sample_number ) < 0 )
    {
        vsapi->setFilterError( "lsmas: failed to output a video frame.", frame_ctx );
        return NULL;
    }
    /* Output video frame. */
    AVFrame    *av_frame = libavsmash_video_get_frame_buffer( vdhp );
    VSFrameRef *vs_frame = make_frame( vohp, av_frame );
    if( !vs_frame )
    {
        vsapi->setFilterError( "lsmas: failed to output a video frame.", frame_ctx );
        return NULL;
    }
    set_frame_properties( vdhp, vi, av_frame, vs_frame, sample_number, vsapi );
    return vs_frame;
}
/*****************************************************************************
 * Others
 *****************************************************************************/
int libavsmash_video_get_track
(
    libavsmash_video_decode_handler_t *vdhp,
    uint32_t                           track_number
)
{
    lw_log_handler_t *lhp = libavsmash_video_get_log_handler( vdhp );
    uint32_t track_id =
        libavsmash_get_track_by_media_type
        (
            libavsmash_video_get_root( vdhp ),
            ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK,
            track_number,
            lhp
        );
    if( track_id == 0 )
        return -1;
    libavsmash_video_set_track_id( vdhp, track_id );
    (void)libavsmash_video_fetch_sample_count   ( vdhp );
    (void)libavsmash_video_fetch_media_duration ( vdhp );
    (void)libavsmash_video_fetch_media_timescale( vdhp );
    return 0;
}