Exemplo n.º 1
0
static AVS_Value initialize_avisynth( avs_handler_t *hp, char *input )
{
    if( load_avisynth_dll( hp ) )
        return avs_void;
    hp->env = hp->func.avs_create_script_environment( AVS_INTERFACE_25 );
    if( hp->func.avs_get_error && hp->func.avs_get_error( hp->env ) )
        return avs_void;
    AVS_Value arg = avs_new_value_string( input );
    AVS_Value res = hp->func.avs_invoke( hp->env, "Import", arg, NULL );
    if( avs_is_error( res ) )
        return res;
    AVS_Value mt_test = hp->func.avs_invoke( hp->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
    int mt_mode = avs_is_int( mt_test ) ? avs_as_int( mt_test ) : 0;
    hp->func.avs_release_value( mt_test );
    if( mt_mode > 0 && mt_mode < 5 )
    {
        AVS_Value temp = hp->func.avs_invoke( hp->env, "Distributor", res, NULL );
        hp->func.avs_release_value( res );
        res = temp;
    }
    hp->clip = hp->func.avs_take_clip( res, hp->env );
    hp->vi   = hp->func.avs_get_video_info( hp->clip );
    if( hp->vi->sample_type & AVS_SAMPLE_FLOAT )
        res = invoke_filter( hp, res, "ConvertAudioTo16bit" );
    return res;
}
Exemplo n.º 2
0
static int avisynth_open_file(AVFormatContext *s) {
    AviSynthContext *avs = (AviSynthContext *)s->priv_data;
    AVS_Value arg, val;
    int ret;
#ifdef _WIN32
    char filename_ansi[MAX_PATH * 4];
    wchar_t filename_wc[MAX_PATH * 4];
#endif

    if (ret = avisynth_context_create(s))
        return ret;

#ifdef _WIN32
    // Convert UTF-8 to ANSI code page
    MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4);
    WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi, MAX_PATH * 4, NULL, NULL);
    arg = avs_new_value_string(filename_ansi);
#else
    arg = avs_new_value_string(s->filename);
#endif
    val = avs_library->avs_invoke(avs->env, "Import", arg, 0);
    if (avs_is_error(val)) {
        av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val));
        ret = AVERROR_UNKNOWN;
        goto fail;
    }
    if (!avs_is_clip(val)) {
        av_log(s, AV_LOG_ERROR, "%s\n", "AviSynth script did not return a clip");
        ret = AVERROR_UNKNOWN;
        goto fail;
    }

    avs->clip = avs_library->avs_take_clip(val, avs->env);
    avs->vi = avs_library->avs_get_video_info(avs->clip);

    // Release the AVS_Value as it will go out of scope.
    avs_library->avs_release_value(val);

    if (ret = avisynth_create_stream(s))
        goto fail;

    return 0;

fail:
    avisynth_context_destroy(avs);
    return ret;
}
Exemplo n.º 3
0
static AVS_VAlue import_d2v_jackie(avs_hnd_t *ah, LPSTR input)
{
    if (!ah->function_exists(ah->env, "MPEG2Dec3_MPEG2Source"))
        return avs_void;
    AVS_Value arg_arr[8] = {
        avs_new_value_string(input),
        avs_new_value_int(ah->d2v.idct),
        avs_new_value_int(ah->d2v.cpu),
        avs_new_value_int(ah->d2v.moderate_h),
        avs_new_value_int(ah->d2v.moderate_v),
        avs_new_value_string(ah->d2v.cpu2),
        avs_new_value_bool(ah->d2v.showq),
        avs_new_value_bool(ah->d2v.fastmc)
    };
    const char *name[8] = {
        NULL, "idct", "cpu", "moderate_h",
        "moderate_v", "cpu2", "showQ", "fastMC"
    };
    AVS_Value arg =avs_new_value_string(input);
    return ah->avs_invoke(ah->env, "MPEG2Dec3_MPEG2Source", avs_new_value_array(arg_arr, 8), name);
}
Exemplo n.º 4
0
static AVS_Value import_d2v_donald(avs_hnd_t *ah, LPSTR input)
{
    if (!ah->func.avs_function_exists(ah->env, "DGDecode_MPEG2Source") && load_dgdecode_dll(ah))
        return avs_void;

    AVS_Value arg_arr[10] = {
        avs_new_value_string(input),
        avs_new_value_int(ah->d2v.upconv),
        avs_new_value_int(ah->d2v.idct),
        avs_new_value_int(ah->d2v.cpu),
        avs_new_value_int(ah->d2v.moderate_h),
        avs_new_value_int(ah->d2v.moderate_v),
        avs_new_value_string(ah->d2v.cpu2),
        avs_new_value_int(ah->d2v.info),
        avs_new_value_bool(ah->d2v.showq),
        avs_new_value_bool(ah->d2v.fastmc)
    };
    const char *name[10] = {
        NULL, "upConv", "idct", "cpu", "moderate_h",
        "moderate_v", "cpu2", "info", "showQ", "fastMC"
    };
    return ah->func.avs_invoke(ah->env, "DGDecode_MPEG2Source", avs_new_value_array(arg_arr, 10), name);
}
Exemplo n.º 5
0
static int load_dgdecode_dll(avs_hnd_t *ah)
{
    if (!(*ah->d2v.dll_path)) {
        HKEY key_handle;
        if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\VFPlugin", 0, KEY_QUERY_VALUE, &key_handle) != ERROR_SUCCESS) {
            RegCloseKey(key_handle);
            return -1;
        }

        DWORD data_size = (DWORD)(sizeof ah->d2v.dll_path);
        LONG ret = RegQueryValueEx(key_handle, "DGIndex", NULL, NULL, (LPBYTE)ah->d2v.dll_path, &data_size);
        RegCloseKey(key_handle);
        if (ret != ERROR_SUCCESS)
            return -1;

        char *n = strstr(ah->d2v.dll_path, "\\DGVfapi.vfp");
        if (n)
            *n = '\0';
        snprintf(ah->d2v.dll_path, sizeof ah->d2v.dll_path, "%s\\DGDecode.dll", ah->d2v.dll_path);
    }
#ifdef DEBUG_ENABLED
    debug_msg("DGDecode.dll=%s", ah->d2v.dll_path);
#endif
    FILE *dll = fopen(ah->d2v.dll_path, "rb");
    if (!dll)
        return -1;
    fclose(dll);

    int ret = 0;
    AVS_Value tmp = ah->func.avs_invoke(ah->env, "LoadPlugin", avs_new_value_string(ah->d2v.dll_path), NULL);
    if (avs_is_error(tmp) || !ah->func.avs_function_exists(ah->env, "DGDecode_MPEG2Source"))
        ret = -1;

    ah->func.avs_release_value(tmp);
    return ret;
}
Exemplo n.º 6
0
static int avisynth_open_file(AVFormatContext *s)
{
    AviSynthContext *avs = s->priv_data;
    AVS_Value arg, val;
    int ret;
#ifdef USING_AVISYNTH
    char filename_ansi[MAX_PATH * 4];
    wchar_t filename_wc[MAX_PATH * 4];
#endif

    if (ret = avisynth_context_create(s))
        return ret;

#ifdef USING_AVISYNTH
    /* Convert UTF-8 to ANSI code page */
    MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4);
    WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi,
                        MAX_PATH * 4, NULL, NULL);
    arg = avs_new_value_string(filename_ansi);
#else
    arg = avs_new_value_string(s->filename);
#endif
    val = avs_library.avs_invoke(avs->env, "Import", arg, 0);
    if (avs_is_error(val)) {
        av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val));
        ret = AVERROR_UNKNOWN;
        goto fail;
    }
    if (!avs_is_clip(val)) {
        av_log(s, AV_LOG_ERROR, "AviSynth script did not return a clip\n");
        ret = AVERROR_UNKNOWN;
        goto fail;
    }

    avs->clip = avs_library.avs_take_clip(val, avs->env);
    avs->vi   = avs_library.avs_get_video_info(avs->clip);

#ifdef USING_AVISYNTH
    /* On Windows, FFmpeg supports AviSynth interface version 6 or higher.
     * This includes AviSynth 2.6 RC1 or higher, and AviSynth+ r1718 or higher,
     * and excludes 2.5 and the 2.6 alphas. Since AvxSynth identifies itself
     * as interface version 3 like 2.5.8, this needs to be special-cased. */

    if (avs_library.avs_get_version(avs->clip) < 6) {
        av_log(s, AV_LOG_ERROR,
               "AviSynth version is too old. Please upgrade to either AviSynth 2.6 >= RC1 or AviSynth+ >= r1718.\n");
        ret = AVERROR_UNKNOWN;
        goto fail;
    }
#endif

    /* Release the AVS_Value as it will go out of scope. */
    avs_library.avs_release_value(val);

    if (ret = avisynth_create_stream(s))
        goto fail;

    return 0;

fail:
    avisynth_context_destroy(avs);
    return ret;
}
Exemplo n.º 7
0
AVS_T *initAVS(const char *filename)
{
    AVS_T *AVS = malloc (sizeof(AVS_T));
    AVS_Value arg0 = avs_new_value_string(filename);
    AVS_Value args = avs_new_value_array(&arg0, 1);

    memset(AVS, 0, sizeof(AVS_T));

#ifdef WIN32_LOADER
    AVS->ldt_fs = Setup_LDT_Keeper();
#endif

    AVS->dll = LoadLibraryA("avisynth.dll");
    if(!AVS->dll)
    {
        mp_msg(MSGT_DEMUX ,MSGL_V, "AVS: failed to load avisynth.dll\n");
        goto avs_err;
    }

    /* Dynamic import of needed stuff from avisynth.dll */
    IMPORT_FUNC(avs_create_script_environment);
    IMPORT_FUNC(avs_invoke);
    IMPORT_FUNC(avs_get_video_info);
    IMPORT_FUNC(avs_take_clip);
    IMPORT_FUNC(avs_release_clip);
    IMPORT_FUNC(avs_get_frame);
    IMPORT_FUNC(avs_release_video_frame);
    IMPORT_FUNC(avs_get_audio);

    AVS->avs_env = AVS->avs_create_script_environment(AVISYNTH_INTERFACE_VERSION);
    if (!AVS->avs_env)
    {
        mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_create_script_environment failed\n");
        goto avs_err;
    }


    AVS->handler = AVS->avs_invoke(AVS->avs_env, "Import", args, 0);

    if (avs_is_error(AVS->handler))
    {
        mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Avisynth error: %s\n", avs_as_string(AVS->handler));
        goto avs_err;
    }

    if (!avs_is_clip(AVS->handler))
    {
        mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Avisynth doesn't return a clip\n");
        goto avs_err;
    }

    return AVS;

avs_err:
    if (AVS->dll) FreeLibrary(AVS->dll);
#ifdef WIN32_LOADER
    Restore_LDT_Keeper(AVS->ldt_fs);
#endif
    free(AVS);
    return NULL;
}
Exemplo n.º 8
0
Arquivo: avs.c Projeto: xing2fan/x264
static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
{
    FILE *fh = x264_fopen( psz_filename, "r" );
    if( !fh )
        return -1;
    int b_regular = x264_is_regular_file( fh );
    fclose( fh );
    FAIL_IF_ERROR( !b_regular, "AVS input is incompatible with non-regular file `%s'\n", psz_filename );

    avs_hnd_t *h = calloc( 1, sizeof(avs_hnd_t) );
    if( !h )
        return -1;
    FAIL_IF_ERROR( custom_avs_load_library( h ), "failed to load avisynth\n" );
    h->env = h->func.avs_create_script_environment( AVS_INTERFACE_25 );
    if( h->func.avs_get_error )
    {
        const char *error = h->func.avs_get_error( h->env );
        FAIL_IF_ERROR( error, "%s\n", error );
    }
    float avs_version = get_avs_version( h );
    if( avs_version <= 0 )
        return -1;
    x264_cli_log( "avs", X264_LOG_DEBUG, "using avisynth version %.2f\n", avs_version );

#ifdef _WIN32
    /* Avisynth doesn't support Unicode filenames. */
    char ansi_filename[MAX_PATH];
    FAIL_IF_ERROR( !x264_ansi_filename( psz_filename, ansi_filename, MAX_PATH, 0 ), "invalid ansi filename\n" );
    AVS_Value arg = avs_new_value_string( ansi_filename );
#else
    AVS_Value arg = avs_new_value_string( psz_filename );
#endif

    AVS_Value res;
    char *filename_ext = get_filename_extension( psz_filename );

    if( !strcasecmp( filename_ext, "avs" ) )
    {
        res = h->func.avs_invoke( h->env, "Import", arg, NULL );
        FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_error( res ) );
        /* check if the user is using a multi-threaded script and apply distributor if necessary.
           adapted from avisynth's vfw interface */
        AVS_Value mt_test = h->func.avs_invoke( h->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
        int mt_mode = avs_is_int( mt_test ) ? avs_as_int( mt_test ) : 0;
        h->func.avs_release_value( mt_test );
        if( mt_mode > 0 && mt_mode < 5 )
        {
            AVS_Value temp = h->func.avs_invoke( h->env, "Distributor", res, NULL );
            h->func.avs_release_value( res );
            res = temp;
        }
    }
    else /* non script file */
    {
        /* cycle through known source filters to find one that works */
        const char *filter[AVS_MAX_SEQUENCE+1] = { 0 };
        avs_build_filter_sequence( filename_ext, filter );
        int i;
        for( i = 0; filter[i]; i++ )
        {
            x264_cli_log( "avs", X264_LOG_INFO, "trying %s... ", filter[i] );
            if( !h->func.avs_function_exists( h->env, filter[i] ) )
            {
                x264_cli_printf( X264_LOG_INFO, "not found\n" );
                continue;
            }
            if( !strncasecmp( filter[i], "FFmpegSource", 12 ) )
            {
                x264_cli_printf( X264_LOG_INFO, "indexing... " );
                fflush( stderr );
            }
            res = h->func.avs_invoke( h->env, filter[i], arg, NULL );
            if( !avs_is_error( res ) )
            {
                x264_cli_printf( X264_LOG_INFO, "succeeded\n" );
                break;
            }
            x264_cli_printf( X264_LOG_INFO, "failed\n" );
        }
        FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename );
    }
    FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename );
    h->clip = h->func.avs_take_clip( res, h->env );
    const AVS_VideoInfo *vi = h->func.avs_get_video_info( h->clip );
    FAIL_IF_ERROR( !avs_has_video( vi ), "`%s' has no video data\n", psz_filename );
    /* if the clip is made of fields instead of frames, call weave to make them frames */
    if( avs_is_field_based( vi ) )
    {
        x264_cli_log( "avs", X264_LOG_WARNING, "detected fieldbased (separated) input, weaving to frames\n" );
        AVS_Value tmp = h->func.avs_invoke( h->env, "Weave", res, NULL );
        FAIL_IF_ERROR( avs_is_error( tmp ), "couldn't weave fields into frames: %s\n", avs_as_error( tmp ) );
        res = update_clip( h, &vi, tmp, res );
        info->interlaced = 1;
        info->tff = avs_is_tff( vi );
    }
#if !HAVE_SWSCALE
    /* if swscale is not available, convert the CSP if necessary */
    FAIL_IF_ERROR( avs_version < 2.6f && (opt->output_csp == X264_CSP_I400 || opt->output_csp == X264_CSP_I422 || opt->output_csp == X264_CSP_I444),
                   "avisynth >= 2.6 is required for i400/i422/i444 output\n" );
    if( (opt->output_csp == X264_CSP_I400 && !AVS_IS_Y( vi )) ||
        (opt->output_csp == X264_CSP_I420 && !AVS_IS_420( vi )) ||
        (opt->output_csp == X264_CSP_I422 && !AVS_IS_422( vi )) ||
        (opt->output_csp == X264_CSP_I444 && !AVS_IS_444( vi )) ||
        (opt->output_csp == X264_CSP_RGB && !avs_is_rgb( vi )) )
    {
        const char *csp;
        if( AVS_IS_AVISYNTHPLUS )
        {
            csp = opt->output_csp == X264_CSP_I400 ? "Y" :
                  opt->output_csp == X264_CSP_I420 ? "YUV420" :
                  opt->output_csp == X264_CSP_I422 ? "YUV422" :
                  opt->output_csp == X264_CSP_I444 ? "YUV444" :
                  "RGB";
        }
        else
        {
            csp = opt->output_csp == X264_CSP_I400 ? "Y8" :
                  opt->output_csp == X264_CSP_I420 ? "YV12" :
                  opt->output_csp == X264_CSP_I422 ? "YV16" :
                  opt->output_csp == X264_CSP_I444 ? "YV24" :
                  "RGB";
        }
        x264_cli_log( "avs", X264_LOG_WARNING, "converting input clip to %s\n", csp );
        if( opt->output_csp != X264_CSP_I400 )
        {
            FAIL_IF_ERROR( opt->output_csp < X264_CSP_I444 && (vi->width&1),
                           "input clip width not divisible by 2 (%dx%d)\n", vi->width, vi->height );
            FAIL_IF_ERROR( opt->output_csp == X264_CSP_I420 && info->interlaced && (vi->height&3),
                           "input clip height not divisible by 4 (%dx%d)\n", vi->width, vi->height );
            FAIL_IF_ERROR( (opt->output_csp == X264_CSP_I420 || info->interlaced) && (vi->height&1),
                           "input clip height not divisible by 2 (%dx%d)\n", vi->width, vi->height );
        }
        char conv_func[16];
        snprintf( conv_func, sizeof(conv_func), "ConvertTo%s", csp );
        AVS_Value arg_arr[3];
        const char *arg_name[3];
        int arg_count = 1;
        arg_arr[0] = res;
        arg_name[0] = NULL;
        if( opt->output_csp != X264_CSP_I400 )
        {
            arg_arr[arg_count] = avs_new_value_bool( info->interlaced );
            arg_name[arg_count] = "interlaced";
            arg_count++;
        }
        /* if doing a rgb <-> yuv conversion then range is handled via 'matrix'. though it's only supported in 2.56+ */
        char matrix[7];
        if( avs_version >= 2.56f && ((opt->output_csp == X264_CSP_RGB && avs_is_yuv( vi )) || (opt->output_csp != X264_CSP_RGB && avs_is_rgb( vi ))) )
        {
            // if converting from yuv, then we specify the matrix for the input, otherwise use the output's.
            int use_pc_matrix = avs_is_yuv( vi ) ? opt->input_range == RANGE_PC : opt->output_range == RANGE_PC;
            snprintf( matrix, sizeof(matrix), "%s601", use_pc_matrix ? "PC." : "Rec" ); /* FIXME: use correct coefficients */
            arg_arr[arg_count] = avs_new_value_string( matrix );
            arg_name[arg_count] = "matrix";
            arg_count++;
            // notification that the input range has changed to the desired one
            opt->input_range = opt->output_range;
        }
        AVS_Value res2 = h->func.avs_invoke( h->env, conv_func, avs_new_value_array( arg_arr, arg_count ), arg_name );
        FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert input clip to %s: %s\n", csp, avs_as_error( res2 ) );
        res = update_clip( h, &vi, res2, res );
    }
    /* if swscale is not available, change the range if necessary. This only applies to YUV-based CSPs however */
    if( avs_is_yuv( vi ) && opt->output_range != RANGE_AUTO && ((opt->input_range == RANGE_PC) != opt->output_range) )
    {
        const char *levels = opt->output_range ? "TV->PC" : "PC->TV";
        x264_cli_log( "avs", X264_LOG_WARNING, "performing %s conversion\n", levels );
        AVS_Value arg_arr[2];
        arg_arr[0] = res;
        arg_arr[1] = avs_new_value_string( levels );
        const char *arg_name[] = { NULL, "levels" };
        AVS_Value res2 = h->func.avs_invoke( h->env, "ColorYUV", avs_new_value_array( arg_arr, 2 ), arg_name );
        FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert range: %s\n", avs_as_error( res2 ) );
        res = update_clip( h, &vi, res2, res );
        // notification that the input range has changed to the desired one
        opt->input_range = opt->output_range;
    }
#endif

    h->func.avs_release_value( res );

    info->width   = vi->width;
    info->height  = vi->height;
    info->fps_num = vi->fps_numerator;
    info->fps_den = vi->fps_denominator;
    h->num_frames = info->num_frames = vi->num_frames;
    info->thread_safe = 1;
    if( AVS_IS_RGB64( vi ) )
        info->csp = X264_CSP_BGRA | X264_CSP_VFLIP | X264_CSP_HIGH_DEPTH;
    else if( avs_is_rgb32( vi ) )
        info->csp = X264_CSP_BGRA | X264_CSP_VFLIP;
    else if( AVS_IS_RGB48( vi ) )
        info->csp = X264_CSP_BGR | X264_CSP_VFLIP | X264_CSP_HIGH_DEPTH;
    else if( avs_is_rgb24( vi ) )
        info->csp = X264_CSP_BGR | X264_CSP_VFLIP;
    else if( AVS_IS_YUV444P16( vi ) )
        info->csp = X264_CSP_I444 | X264_CSP_HIGH_DEPTH;
    else if( avs_is_yv24( vi ) )
        info->csp = X264_CSP_I444;
    else if( AVS_IS_YUV422P16( vi ) )
        info->csp = X264_CSP_I422 | X264_CSP_HIGH_DEPTH;
    else if( avs_is_yv16( vi ) )
        info->csp = X264_CSP_I422;
    else if( AVS_IS_YUV420P16( vi ) )
        info->csp = X264_CSP_I420 | X264_CSP_HIGH_DEPTH;
    else if( avs_is_yv12( vi ) )
        info->csp = X264_CSP_I420;
    else if( AVS_IS_Y16( vi ) )
        info->csp = X264_CSP_I400 | X264_CSP_HIGH_DEPTH;
    else if( avs_is_y8( vi ) )
        info->csp = X264_CSP_I400;
    else if( avs_is_yuy2( vi ) )
        info->csp = X264_CSP_YUYV;
#if HAVE_SWSCALE
    else if( avs_is_yv411( vi ) )
        info->csp = AV_PIX_FMT_YUV411P | X264_CSP_OTHER;
#endif
    else
    {
        AVS_Value pixel_type = h->func.avs_invoke( h->env, "PixelType", res, NULL );
        const char *pixel_type_name = avs_is_string( pixel_type ) ? avs_as_string( pixel_type ) : "unknown";
        FAIL_IF_ERROR( 1, "not supported pixel type: %s\n", pixel_type_name );
    }
    info->vfr = 0;

    *p_handle = h;
    return 0;
}
Exemplo n.º 9
0
static AVS_Value import_avs(avs_hnd_t *ah, LPSTR input)
{
    AVS_Value arg = avs_new_value_string(input);
    return ah->func.avs_invoke(ah->env, "Import", arg, NULL);
}
Exemplo n.º 10
0
struct AVS_Value* inline_avs_new_value_string(AVS_Value * ptr, const char* v0) 
{
    if(ptr)
	*ptr = avs_new_value_string(v0);
    return ptr;
}
Exemplo n.º 11
0
static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
{
    FILE *fh = fopen( psz_filename, "r" );
    if( !fh )
        return -1;
    FAIL_IF_ERROR( !x264_is_regular_file( fh ), "AVS input is incompatible with non-regular file `%s'\n", psz_filename );
    fclose( fh );

    avs_hnd_t *h = malloc( sizeof(avs_hnd_t) );
    if( !h )
        return -1;
    FAIL_IF_ERROR( x264_avs_load_library( h ), "failed to load avisynth\n" )
    h->env = h->func.avs_create_script_environment( AVS_INTERFACE_25 );
    FAIL_IF_ERROR( !h->env, "failed to initiate avisynth\n" )
    AVS_Value arg = avs_new_value_string( psz_filename );
    AVS_Value res;
    char *filename_ext = get_filename_extension( psz_filename );

    if( !strcasecmp( filename_ext, "avs" ) )
    {
        res = h->func.avs_invoke( h->env, "Import", arg, NULL );
        FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_string( res ) )
        /* check if the user is using a multi-threaded script and apply distributor if necessary.
           adapted from avisynth's vfw interface */
        AVS_Value mt_test = h->func.avs_invoke( h->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
        int mt_mode = avs_is_int( mt_test ) ? avs_as_int( mt_test ) : 0;
        h->func.avs_release_value( mt_test );
        if( mt_mode > 0 && mt_mode < 5 )
        {
            AVS_Value temp = h->func.avs_invoke( h->env, "Distributor", res, NULL );
            h->func.avs_release_value( res );
            res = temp;
        }
    }
    else /* non script file */
    {
        /* cycle through known source filters to find one that works */
        const char *filter[AVS_MAX_SEQUENCE+1] = { 0 };
        avs_build_filter_sequence( filename_ext, filter );
        int i;
        for( i = 0; filter[i]; i++ )
        {
            x264_cli_log( "avs", X264_LOG_INFO, "trying %s... ", filter[i] );
            if( !h->func.avs_function_exists( h->env, filter[i] ) )
            {
                x264_cli_printf( X264_LOG_INFO, "not found\n" );
                continue;
            }
            if( !strncasecmp( filter[i], "FFmpegSource", 12 ) )
            {
                x264_cli_printf( X264_LOG_INFO, "indexing... " );
                fflush( stderr );
            }
            res = h->func.avs_invoke( h->env, filter[i], arg, NULL );
            if( !avs_is_error( res ) )
            {
                x264_cli_printf( X264_LOG_INFO, "succeeded\n" );
                break;
            }
            x264_cli_printf( X264_LOG_INFO, "failed\n" );
        }
        FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename )
    }
    FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename )
    h->clip = h->func.avs_take_clip( res, h->env );
    const AVS_VideoInfo *vi = h->func.avs_get_video_info( h->clip );
    FAIL_IF_ERROR( !avs_has_video( vi ), "`%s' has no video data\n", psz_filename )
    /* if the clip is made of fields instead of frames, call weave to make them frames */
    if( avs_is_field_based( vi ) )
    {
        x264_cli_log( "avs", X264_LOG_WARNING, "detected fieldbased (separated) input, weaving to frames\n" );
        AVS_Value tmp = h->func.avs_invoke( h->env, "Weave", res, NULL );
        FAIL_IF_ERROR( avs_is_error( tmp ), "couldn't weave fields into frames\n" )
        res = update_clip( h, &vi, tmp, res );
        info->interlaced = 1;
        info->tff = avs_is_tff( vi );
    }
#if !HAVE_SWSCALE
    /* if swscale is not available, convert CSPs to yv12 */
    if( !avs_is_yv12( vi ) )
    {
        x264_cli_log( "avs", X264_LOG_WARNING, "converting input clip to YV12\n" );
        FAIL_IF_ERROR( vi->width&1 || vi->height&1, "input clip width or height not divisible by 2 (%dx%d)\n", vi->width, vi->height )
        const char *arg_name[2] = { NULL, "interlaced" };
        AVS_Value arg_arr[2] = { res, avs_new_value_bool( info->interlaced ) };
        AVS_Value res2 = h->func.avs_invoke( h->env, "ConvertToYV12", avs_new_value_array( arg_arr, 2 ), arg_name );
        FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert input clip to YV12\n" )
        res = update_clip( h, &vi, res2, res );
    }