Beispiel #1
0
uint Tps61045Lv(uint Lv) {    
    uint Bank;

    CLIP_VALUE(Lv, 0, 100);
    Bank = Lv * TpsRes.MaxLv / 100;
    CLIP_VALUE(Bank, 1, TpsRes.MaxLv);
    return Bank;
}
AVSValue __cdecl CreateLSMASHVideoSource( AVSValue args, void *user_data, IScriptEnvironment *env )
{
#ifdef NDEBUG
    av_log_set_level( AV_LOG_QUIET );
#endif
    const char *source                 = args[0].AsString();
    uint32_t    track_number           = args[1].AsInt( 0 );
    int         threads                = args[2].AsInt( 0 );
    int         seek_mode              = args[3].AsInt( 0 );
    uint32_t    forward_seek_threshold = args[4].AsInt( 10 );
    int         direct_rendering       = args[5].AsBool( false ) ? 1 : 0;
    int         stacked_format         = args[6].AsBool( false ) ? 1 : 0;
    enum AVPixelFormat pixel_format    = get_av_output_pixel_format( args[7].AsString( NULL ) );
    threads                = threads >= 0 ? threads : 0;
    seek_mode              = CLIP_VALUE( seek_mode, 0, 2 );
    forward_seek_threshold = CLIP_VALUE( forward_seek_threshold, 1, 999 );
    direct_rendering      &= (pixel_format == AV_PIX_FMT_NONE);
    return new LSMASHVideoSource( source, track_number, threads, seek_mode, forward_seek_threshold,
                                  direct_rendering, stacked_format, pixel_format, env );
}
Beispiel #3
0
static BOOL CALLBACK dialog_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
    static char edit_buf[256] = { 0 };
    switch( message )
    {
        case WM_INITDIALOG :
            InitCommonControls();
            get_settings();
            /* threads */
            sprintf( edit_buf, "%d", reader_opt.threads );
            SetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPCTSTR)edit_buf );
            SendMessage( GetDlgItem( hwnd, IDC_SPIN_THREADS ), UDM_SETBUDDY, (WPARAM)GetDlgItem( hwnd, IDC_EDIT_THREADS ), 0 );
            /* av_sync */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_AV_SYNC ), BM_SETCHECK, (WPARAM) reader_opt.av_sync ? BST_CHECKED : BST_UNCHECKED, 0 );
            /* no_create_index */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_CREATE_INDEX_FILE ), BM_SETCHECK, (WPARAM) reader_opt.no_create_index ? BST_UNCHECKED : BST_CHECKED, 0 );
            /* force stream index */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_VIDEO ), BM_SETCHECK, (WPARAM) reader_opt.force_video ? BST_CHECKED : BST_UNCHECKED, 0 );
            sprintf( edit_buf, "%d", reader_opt.force_video_index );
            SetDlgItemText( hwnd, IDC_EDIT_FORCE_VIDEO_INDEX, (LPCTSTR)edit_buf );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_AUDIO ), BM_SETCHECK, (WPARAM) reader_opt.force_audio ? BST_CHECKED : BST_UNCHECKED, 0 );
            sprintf( edit_buf, "%d", reader_opt.force_audio_index );
            SetDlgItemText( hwnd, IDC_EDIT_FORCE_AUDIO_INDEX, (LPCTSTR)edit_buf );
            /* forward_seek_threshold */
            sprintf( edit_buf, "%d", video_opt->forward_seek_threshold );
            SetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPCTSTR)edit_buf );
            SendMessage( GetDlgItem( hwnd, IDC_SPIN_FORWARD_THRESHOLD ), UDM_SETBUDDY, (WPARAM)GetDlgItem( hwnd, IDC_EDIT_FORWARD_THRESHOLD ), 0 );
            /* seek mode */
            HWND hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_SEEK_MODE );
            for( int i = 0; i < 3; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)seek_mode_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->seek_mode, 0 );
            /* scaler */
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_SCALER );
            for( int i = 0; i < 11; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)scaler_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->scaler, 0 );
            /* apply_repeat_flag */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_APPLY_REPEAT_FLAG ), BM_SETCHECK, (WPARAM) video_opt->apply_repeat_flag ? BST_CHECKED : BST_UNCHECKED, 0 );
            /* field_dominance */
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_FIELD_DOMINANCE );
            for( int i = 0; i < 3; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)field_dominance_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->field_dominance, 0 );
            /* LW48 output */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_LW48_OUTPUT ), BM_SETCHECK, (WPARAM) video_opt->colorspace == 0 ? BST_UNCHECKED : BST_CHECKED, 0 );
            /* AVS bit-depth */
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_AVS_BITDEPTH );
            for( int i = 0; i < 4; i++ )
            {
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)avs_bit_depth_list[i] );
                if( video_opt->avs.bit_depth == atoi( avs_bit_depth_list[i] ) )
                    SendMessage( hcombo, CB_SETCURSEL, i, 0 );
            }
            /* audio_delay */
            sprintf( edit_buf, "%d", audio_delay );
            SetDlgItemText( hwnd, IDC_EDIT_AUDIO_DELAY, (LPCTSTR)edit_buf );
            /* channel_layout */
            if( audio_opt->channel_layout )
            {
                char *buf = edit_buf;
                for( int i = 0; i < 64; i++ )
                {
                    uint64_t audio_channel = audio_opt->channel_layout & (1ULL << i);
                    if( audio_channel )
                    {
                        const char *channel_name = av_get_channel_name( audio_channel );
                        if( channel_name )
                        {
                            int name_length = strlen( channel_name );
                            memcpy( buf, channel_name, name_length );
                            buf += name_length;
                            *(buf++) = '+';
                        }
                    }
                }
                if( buf > edit_buf )
                    *(buf - 1) = '\0';  /* Set NULL terminator. */
                else
                    memcpy( edit_buf, "Unspecified", 12 );
            }
            else
                memcpy( edit_buf, "Unspecified", 12 );
            SetDlgItemText( hwnd, IDC_EDIT_CHANNEL_LAYOUT, (LPCTSTR)edit_buf );
            /* sample_rate */
            if( audio_opt->sample_rate > 0 )
                sprintf( edit_buf, "%d", audio_opt->sample_rate );
            else
            {
                audio_opt->sample_rate = 0;
                memcpy( edit_buf, "0 (Auto)", 12 );
            }
            SetDlgItemText( hwnd, IDC_EDIT_SAMPLE_RATE, (LPCTSTR)edit_buf );
            /* mix_level */
            send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER,   IDC_TEXT_MIX_LEVEL_CENTER,   0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ], edit_buf );
            send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND, IDC_TEXT_MIX_LEVEL_SURROUND, 0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND], edit_buf );
            send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_LFE,      IDC_TEXT_MIX_LEVEL_LFE,      0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ], edit_buf );
            /* readers */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAVSMASH_INPUT ), BM_SETCHECK, (WPARAM) reader_disabled[0] ? BST_UNCHECKED : BST_CHECKED, 0 );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_AVS_INPUT        ), BM_SETCHECK, (WPARAM) reader_disabled[1] ? BST_UNCHECKED : BST_CHECKED, 0 );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_VPY_INPUT        ), BM_SETCHECK, (WPARAM) reader_disabled[2] ? BST_UNCHECKED : BST_CHECKED, 0 );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAV_INPUT      ), BM_SETCHECK, (WPARAM) reader_disabled[3] ? BST_UNCHECKED : BST_CHECKED, 0 );
            /* dummy reader */
            sprintf( edit_buf, "%d", video_opt->dummy.width );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_WIDTH, (LPCTSTR)edit_buf );
            sprintf( edit_buf, "%d", video_opt->dummy.height );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_HEIGHT, (LPCTSTR)edit_buf );
            sprintf( edit_buf, "%d", video_opt->dummy.framerate_num );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_NUM, (LPCTSTR)edit_buf );
            sprintf( edit_buf, "%d", video_opt->dummy.framerate_den );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_DEN, (LPCTSTR)edit_buf );
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_DUMMY_COLORSPACE );
            for( int i = 0; i < 3; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)dummy_colorspace_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->dummy.colorspace, 0 );
            /* Library informations */
            if( plugin_information[0] == 0 )
                get_plugin_information();
            SetDlgItemText( hwnd, IDC_TEXT_LIBRARY_INFO, (LPCTSTR)plugin_information );
            HFONT hfont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
            LOGFONT lf = { 0 };
            GetObject( hfont, sizeof(lf), &lf );
            lf.lfWidth  *= 0.90;
            lf.lfHeight *= 0.90;
            lf.lfQuality = ANTIALIASED_QUALITY;
            SendMessage( GetDlgItem( hwnd, IDC_TEXT_LIBRARY_INFO ), WM_SETFONT, (WPARAM)CreateFontIndirect( &lf ), 1 );
            return TRUE;
        case WM_NOTIFY :
            if( wparam == IDC_SPIN_THREADS )
            {
                LPNMUPDOWN lpnmud = (LPNMUPDOWN)lparam;
                if( lpnmud->hdr.code == UDN_DELTAPOS )
                {
                    GetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.threads = atoi( edit_buf );
                    if( lpnmud->iDelta )
                        reader_opt.threads += lpnmud->iDelta > 0 ? -1 : 1;
                    if( reader_opt.threads < 0 )
                        reader_opt.threads = 0;
                    sprintf( edit_buf, "%d", reader_opt.threads );
                    SetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPCTSTR)edit_buf );
                }
            }
            else if( wparam == IDC_SPIN_FORWARD_THRESHOLD )
            {
                LPNMUPDOWN lpnmud = (LPNMUPDOWN)lparam;
                if( lpnmud->hdr.code == UDN_DELTAPOS )
                {
                    GetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->forward_seek_threshold = atoi( edit_buf );
                    if( lpnmud->iDelta )
                        video_opt->forward_seek_threshold += lpnmud->iDelta > 0 ? -1 : 1;
                    video_opt->forward_seek_threshold = CLIP_VALUE( video_opt->forward_seek_threshold, 1, 999 );
                    sprintf( edit_buf, "%d", video_opt->forward_seek_threshold );
                    SetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPCTSTR)edit_buf );
                }
            }
            return TRUE;
        case WM_HSCROLL :
            if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER ) == (HWND)lparam )
                get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER,   IDC_TEXT_MIX_LEVEL_CENTER,   &audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ], edit_buf );
            else if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND ) == (HWND)lparam )
                get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND, IDC_TEXT_MIX_LEVEL_SURROUND, &audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND], edit_buf );
            else if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_LFE ) == (HWND)lparam )
                get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_LFE,      IDC_TEXT_MIX_LEVEL_LFE,      &audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ], edit_buf );
            return FALSE;
        case WM_COMMAND :
            switch( wparam )
            {
                case IDCANCEL :
                    EndDialog( hwnd, IDCANCEL );
                    return TRUE;
                case IDOK :
                {
                    if( !settings_path )
                        settings_path = (char *)settings_path_list[0];
                    FILE *ini = fopen( settings_path, "w" );
                    if( !ini )
                    {
                        MESSAGE_BOX_DESKTOP( MB_ICONERROR | MB_OK, "Failed to update configuration file" );
                        return FALSE;
                    }
                    /* threads */
                    GetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.threads = MAX( atoi( edit_buf ), 0 );
                    if( reader_opt.threads > 0 )
                        fprintf( ini, "threads=%d\n", reader_opt.threads );
                    else
                        fprintf( ini, "threads=0 (auto)\n" );
                    /* av_sync */
                    reader_opt.av_sync = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_AV_SYNC ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "av_sync=%d\n", reader_opt.av_sync );
                    /* no_create_index */
                    reader_opt.no_create_index = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_CREATE_INDEX_FILE ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "no_create_index=%d\n", reader_opt.no_create_index );
                    /* force stream index */
                    reader_opt.force_video = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_VIDEO ), BM_GETCHECK, 0, 0 ));
                    GetDlgItemText( hwnd, IDC_EDIT_FORCE_VIDEO_INDEX, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.force_video_index = MAX( atoi( edit_buf ), -1 );
                    fprintf( ini, "force_video_index=%d:%d\n", reader_opt.force_video, reader_opt.force_video_index );
                    reader_opt.force_audio = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_AUDIO ), BM_GETCHECK, 0, 0 ));
                    GetDlgItemText( hwnd, IDC_EDIT_FORCE_AUDIO_INDEX, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.force_audio_index = MAX( atoi( edit_buf ), -1 );
                    fprintf( ini, "force_audio_index=%d:%d\n", reader_opt.force_audio, reader_opt.force_audio_index );
                    /* seek_mode */
                    video_opt->seek_mode = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_SEEK_MODE ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "seek_mode=%d\n", video_opt->seek_mode );
                    /* forward_seek_threshold */
                    GetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->forward_seek_threshold = CLIP_VALUE( atoi( edit_buf ), 1, 999 );
                    fprintf( ini, "forward_threshold=%d\n", video_opt->forward_seek_threshold );
                    /* scaler */
                    video_opt->scaler = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_SCALER ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "scaler=%d\n", video_opt->scaler );
                    /* apply_repeat_flag */
                    video_opt->apply_repeat_flag = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_APPLY_REPEAT_FLAG ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "apply_repeat_flag=%d\n", video_opt->apply_repeat_flag );
                    /* field_dominance */
                    video_opt->field_dominance = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_FIELD_DOMINANCE ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "field_dominance=%d\n", video_opt->field_dominance );
                    /* LW48 output */
                    video_opt->colorspace = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_LW48_OUTPUT ), BM_GETCHECK, 0, 0 )) ? OUTPUT_LW48 : 0;
                    fprintf( ini, "colorspace=%d\n", video_opt->colorspace );
                    /* AVS bit-depth */
                    video_opt->avs.bit_depth = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_AVS_BITDEPTH ), CB_GETCURSEL, 0, 0 );
                    video_opt->avs.bit_depth = atoi( avs_bit_depth_list[ video_opt->avs.bit_depth ] );
                    fprintf( ini, "avs_bit_depth=%d\n", video_opt->avs.bit_depth );
                    /* audio_delay */
                    GetDlgItemText( hwnd, IDC_EDIT_AUDIO_DELAY, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    audio_delay = atoi( edit_buf );
                    fprintf( ini, "audio_delay=%d\n", audio_delay );
                    /* channel_layout */
                    GetDlgItemText( hwnd, IDC_EDIT_CHANNEL_LAYOUT, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    audio_opt->channel_layout = av_get_channel_layout( edit_buf );
                    fprintf( ini, "channel_layout=0x%"PRIx64"\n", audio_opt->channel_layout );
                    /* sample_rate */
                    GetDlgItemText( hwnd, IDC_EDIT_SAMPLE_RATE, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    audio_opt->sample_rate = atoi( edit_buf );
                    fprintf( ini, "sample_rate=%d\n", audio_opt->sample_rate );
                    /* mix_level */
                    fprintf( ini, "mix_level=%d:%d:%d\n",
                             audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ],
                             audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND],
                             audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ] );
                    /* readers */
                    reader_disabled[0] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAVSMASH_INPUT ), BM_GETCHECK, 0, 0 ));
                    reader_disabled[1] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_AVS_INPUT        ), BM_GETCHECK, 0, 0 ));
                    reader_disabled[2] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_VPY_INPUT        ), BM_GETCHECK, 0, 0 ));
                    reader_disabled[3] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAV_INPUT      ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "libavsmash_disabled=%d\n", reader_disabled[0] );
                    fprintf( ini, "avs_disabled=%d\n",        reader_disabled[1] );
                    fprintf( ini, "vpy_disabled=%d\n",        reader_disabled[2] );
                    fprintf( ini, "libav_disabled=%d\n",      reader_disabled[3] );
                    /* dummy reader */
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_WIDTH, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.width = MAX( atoi( edit_buf ), 32 );
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_HEIGHT, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.height = MAX( atoi( edit_buf ), 32 );
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_NUM, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.framerate_num = MAX( atoi( edit_buf ), 1 );
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_DEN, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.framerate_den = MAX( atoi( edit_buf ), 1 );
                    video_opt->dummy.colorspace = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_DUMMY_COLORSPACE ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "dummy_resolution=%dx%d\n", video_opt->dummy.width, video_opt->dummy.height );
                    fprintf( ini, "dummy_framerate=%d/%d\n", video_opt->dummy.framerate_num, video_opt->dummy.framerate_den );
                    fprintf( ini, "dummy_colorspace=%d\n", video_opt->dummy.colorspace );
                    fclose( ini );
                    EndDialog( hwnd, IDOK );
                    MESSAGE_BOX_DESKTOP( MB_OK, "Please reopen the input file for updating settings!" );
                    return TRUE;
                }
                default :
                    return FALSE;
            }
        case WM_CLOSE :
            EndDialog( hwnd, IDOK );
            return TRUE;
        default :
            return FALSE;
    }
}
Beispiel #4
0
static void get_settings( void )
{
    FILE *ini = open_settings();
    char buf[128];
    if( ini )
    {
        /* threads */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "threads=%d", &reader_opt.threads ) != 1 )
            reader_opt.threads = 0;
        /* av_sync */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "av_sync=%d", &reader_opt.av_sync ) != 1 )
            reader_opt.av_sync = 1;
        /* no_create_index */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "no_create_index=%d", &reader_opt.no_create_index ) != 1 )
            reader_opt.no_create_index = 0;
        /* force stream index */
        if( !fgets( buf, sizeof(buf), ini )
         || sscanf( buf, "force_video_index=%d:%d",
                    &reader_opt.force_video, &reader_opt.force_video_index ) != 2 )
        {
            reader_opt.force_video       = 0;
            reader_opt.force_video_index = -1;
        }
        else
            reader_opt.force_video_index = MAX( reader_opt.force_video_index, -1 );
        if( !fgets( buf, sizeof(buf), ini )
         || sscanf( buf, "force_audio_index=%d:%d",
                    &reader_opt.force_audio, &reader_opt.force_audio_index ) != 2 )
        {
            reader_opt.force_audio       = 0;
            reader_opt.force_audio_index = -1;
        }
        else
            reader_opt.force_audio_index = MAX( reader_opt.force_audio_index, -1 );
        /* seek_mode */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "seek_mode=%d", &video_opt->seek_mode ) != 1 )
            video_opt->seek_mode = 0;
        else
            video_opt->seek_mode = CLIP_VALUE( video_opt->seek_mode, 0, 2 );
        /* forward_seek_threshold */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "forward_threshold=%d", &video_opt->forward_seek_threshold ) != 1 )
            video_opt->forward_seek_threshold = 10;
        else
            video_opt->forward_seek_threshold = CLIP_VALUE( video_opt->forward_seek_threshold, 1, 999 );
        /* scaler */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "scaler=%d", &video_opt->scaler ) != 1 )
            video_opt->scaler = 0;
        else
            video_opt->scaler = CLIP_VALUE( video_opt->scaler, 0, 10 );
        /* apply_repeat_flag */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "apply_repeat_flag=%d", &video_opt->apply_repeat_flag ) != 1 )
            video_opt->apply_repeat_flag = 0;
        /* field_dominance */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "field_dominance=%d", &video_opt->field_dominance ) != 1 )
            video_opt->field_dominance = 0;
        else
            video_opt->field_dominance = CLIP_VALUE( video_opt->field_dominance, 0, 2 );
        /* LW48 output */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "colorspace=%d", (int *)&video_opt->colorspace ) != 1 )
            video_opt->colorspace = 0;
        else
            video_opt->colorspace = video_opt->colorspace ? OUTPUT_LW48 : 0;
        /* AVS bit-depth */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "avs_bit_depth=%d", &video_opt->avs.bit_depth ) != 1 )
            video_opt->avs.bit_depth = 8;
        else
        {
            video_opt->avs.bit_depth = CLIP_VALUE( video_opt->avs.bit_depth, 8, 16 );
            if( video_opt->avs.bit_depth > 10 )
                video_opt->avs.bit_depth = 16;
        }
        /* audio_delay */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "audio_delay=%d", &audio_delay ) != 1 )
            audio_delay = 0;
        /* channel_layout */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "channel_layout=0x%"SCNx64, &audio_opt->channel_layout ) != 1 )
            audio_opt->channel_layout = 0;
        /* sample_rate */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "sample_rate=%d", &audio_opt->sample_rate ) != 1 )
            audio_opt->sample_rate = 0;
        /* mix_level */
        if( !fgets( buf, sizeof(buf), ini )
         || sscanf( buf, "mix_level=%d:%d:%d",
                    &audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ],
                    &audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND],
                    &audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ] ) != 3 )
        {
            audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ] = 71;
            audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] = 71;
            audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ] = 0;
        }
        else
        {
            audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ] = CLIP_VALUE( audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ], 0, 10000 );
            audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] = CLIP_VALUE( audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND], 0, 10000 );
            audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ] = CLIP_VALUE( audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ], 0, 30000 );
        }
        /* readers */
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "libavsmash_disabled=%d", &reader_disabled[0] ) != 1 )
            reader_disabled[0] = 0;
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "avs_disabled=%d",        &reader_disabled[1] ) != 1 )
            reader_disabled[1] = 0;
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "vpy_disabled=%d",        &reader_disabled[2] ) != 1 )
            reader_disabled[2] = 0;
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "libav_disabled=%d",      &reader_disabled[3] ) != 1 )
            reader_disabled[3] = 0;
        /* dummy reader */
        if( !fgets( buf, sizeof(buf), ini )
         || sscanf( buf, "dummy_resolution=%dx%d", &video_opt->dummy.width, &video_opt->dummy.height ) != 2 )
        {
            video_opt->dummy.width  = 720;
            video_opt->dummy.height = 480;
        }
        else
        {
            video_opt->dummy.width  = MAX( video_opt->dummy.width,  32 );
            video_opt->dummy.height = MAX( video_opt->dummy.height, 32 );
        }
        if( !fgets( buf, sizeof(buf), ini )
         || sscanf( buf, "dummy_framerate=%d/%d", &video_opt->dummy.framerate_num, &video_opt->dummy.framerate_den ) != 2 )
        {
            video_opt->dummy.framerate_num = 24;
            video_opt->dummy.framerate_den = 1;
        }
        else
        {
            video_opt->dummy.framerate_num = MAX( video_opt->dummy.framerate_num, 1 );
            video_opt->dummy.framerate_den = MAX( video_opt->dummy.framerate_den, 1 );
        }
        if( !fgets( buf, sizeof(buf), ini ) || sscanf( buf, "dummy_colorspace=%d", (int *)&video_opt->dummy.colorspace ) != 1 )
            video_opt->dummy.colorspace = OUTPUT_YUY2;
        else
            video_opt->dummy.colorspace = CLIP_VALUE( video_opt->dummy.colorspace, 0, 2 );
        fclose( ini );
    }
    else
    {
        /* Set up defalut values. */
        reader_opt.threads                = 0;
        reader_opt.av_sync                = 1;
        reader_opt.no_create_index        = 0;
        reader_opt.force_video            = 0;
        reader_opt.force_video_index      = -1;
        reader_opt.force_audio            = 0;
        reader_opt.force_audio_index      = -1;
        reader_disabled[0]                = 0;
        reader_disabled[1]                = 0;
        reader_disabled[2]                = 0;
        reader_disabled[3]                = 0;
        audio_delay                       = 0;
        video_opt->seek_mode              = 0;
        video_opt->forward_seek_threshold = 10;
        video_opt->scaler                 = 0;
        video_opt->apply_repeat_flag      = 0;
        video_opt->field_dominance        = 0;
        video_opt->colorspace             = 0;
        video_opt->dummy.width            = 720;
        video_opt->dummy.height           = 480;
        video_opt->dummy.framerate_num    = 24;
        video_opt->dummy.framerate_den    = 1;
        video_opt->dummy.colorspace       = OUTPUT_YUY2;
        video_opt->avs.bit_depth          = 8;
        audio_opt->channel_layout         = 0;
        audio_opt->sample_rate            = 0;
        audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ] = 71;
        audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND] = 71;
        audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ] = 0;
    }
}
void VS_CC vs_libavsmashsource_create( const VSMap *in, VSMap *out, void *user_data, VSCore *core, const VSAPI *vsapi )
{
    /* Get file name. */
    const char *file_name = vsapi->propGetData( in, "source", 0, NULL );
    if( !file_name )
    {
        vsapi->setError( out, "lsmas: failed to get source file name." );
        return;
    }
    /* Allocate the handler of this plugin. */
    lsmas_handler_t *hp = alloc_handler();
    if( !hp )
    {
        vsapi->setError( out, "lsmas: failed to allocate the handler." );
        return;
    }
    libavsmash_video_decode_handler_t *vdhp = hp->vdhp;
    libavsmash_video_output_handler_t *vohp = hp->vohp;
    vs_video_output_handler_t *vs_vohp = vs_allocate_video_output_handler( vohp );
    if( !vs_vohp )
    {
        free_handler( &hp );
        vsapi->setError( out, "lsmas: failed to allocate the VapourSynth video output handler." );
        return;
    }
    vohp->private_handler      = vs_vohp;
    vohp->free_private_handler = lw_free;
    /* Set up VapourSynth error handler. */
    vs_basic_handler_t vsbh = { 0 };
    vsbh.out       = out;
    vsbh.frame_ctx = NULL;
    vsbh.vsapi     = vsapi;
    /* Set up log handler. */
    lw_log_handler_t lh = { 0 };
    lh.level    = LW_LOG_FATAL;
    lh.priv     = &vsbh;
    lh.show_log = set_error;
    /* Open source file. */
    uint32_t number_of_tracks = open_file( hp, file_name, &lh );
    if( number_of_tracks == 0 )
    {
        vs_filter_free( hp, core, vsapi );
        return;
    }
    /* Get options. */
    int64_t track_number;
    int64_t threads;
    int64_t seek_mode;
    int64_t seek_threshold;
    int64_t variable_info;
    int64_t direct_rendering;
    int64_t fps_num;
    int64_t fps_den;
    const char *format;
    const char *preferred_decoder_names;
    set_option_int64 ( &track_number,            0,    "track",          in, vsapi );
    set_option_int64 ( &threads,                 0,    "threads",        in, vsapi );
    set_option_int64 ( &seek_mode,               0,    "seek_mode",      in, vsapi );
    set_option_int64 ( &seek_threshold,          10,   "seek_threshold", in, vsapi );
    set_option_int64 ( &variable_info,           0,    "variable",       in, vsapi );
    set_option_int64 ( &direct_rendering,        0,    "dr",             in, vsapi );
    set_option_int64 ( &fps_num,                 0,    "fpsnum",         in, vsapi );
    set_option_int64 ( &fps_den,                 1,    "fpsden",         in, vsapi );
    set_option_string( &format,                  NULL, "format",         in, vsapi );
    set_option_string( &preferred_decoder_names, NULL, "decoder",        in, vsapi );
    set_preferred_decoder_names_on_buf( hp->preferred_decoder_names_buf, preferred_decoder_names );
    libavsmash_video_set_seek_mode              ( vdhp, CLIP_VALUE( seek_mode,      0, 2 ) );
    libavsmash_video_set_forward_seek_threshold ( vdhp, CLIP_VALUE( seek_threshold, 1, 999 ) );
    libavsmash_video_set_preferred_decoder_names( vdhp, tokenize_preferred_decoder_names( hp->preferred_decoder_names_buf ) );
    vohp->vfr2cfr = (fps_num > 0 && fps_den > 0);
    vohp->cfr_num = (uint32_t)fps_num;
    vohp->cfr_den = (uint32_t)fps_den;
    vs_vohp->variable_info               = CLIP_VALUE( variable_info,  0, 1 );
    vs_vohp->direct_rendering            = CLIP_VALUE( direct_rendering,  0, 1 ) && !format;
    vs_vohp->vs_output_pixel_format = vs_vohp->variable_info ? pfNone : get_vs_output_pixel_format( format );
    if( track_number && track_number > number_of_tracks )
    {
        vs_filter_free( hp, core, vsapi );
        set_error_on_init( out, vsapi, "lsmas: the number of tracks equals %"PRIu32".", number_of_tracks );
        return;
    }
    libavsmash_video_set_log_handler( vdhp, &lh );
    /* Get video track. */
    if( libavsmash_video_get_track( vdhp, track_number ) < 0 )
    {
        vs_filter_free( hp, core, vsapi );
        return;
    }
    /* Set up decoders for this track. */
    threads = threads >= 0 ? threads : 0;
    if( prepare_video_decoding( hp, threads, out, core, vsapi ) < 0 )
    {
        vs_filter_free( hp, core, vsapi );
        return;
    }
    lsmash_discard_boxes( libavsmash_video_get_root( vdhp ) );
    vsapi->createFilter( in, out, "LibavSMASHSource", vs_filter_init, vs_filter_get_frame, vs_filter_free, fmUnordered, nfMakeLinear, hp, core );
    return;
}
void VS_CC vs_lwlibavsource_create( const VSMap *in, VSMap *out, void *user_data, VSCore *core, const VSAPI *vsapi )
{
    /* Get file path. */
    const char *file_path = vsapi->propGetData( in, "source", 0, NULL );
    if( !file_path )
    {
        vsapi->setError( out, "lsmas: failed to get source file name." );
        return;
    }
    /* Allocate the handler of this filter function. */
    lwlibav_handler_t *hp = alloc_handler();
    if( !hp )
    {
        vsapi->setError( out, "lsmas: failed to allocate the LW-Libav handler." );
        return;
    }
    lwlibav_file_handler_t         *lwhp = &hp->lwh;
    lwlibav_video_decode_handler_t *vdhp = hp->vdhp;
    lwlibav_video_output_handler_t *vohp = hp->vohp;
    vs_video_output_handler_t *vs_vohp = vs_allocate_video_output_handler( vohp );
    if( !vs_vohp )
    {
        free_handler( &hp );
        vsapi->setError( out, "lsmas: failed to allocate the VapourSynth video output handler." );
        return;
    }
    vohp->private_handler      = vs_vohp;
    vohp->free_private_handler = lw_free;
    /* Set up VapourSynth error handler. */
    vs_basic_handler_t vsbh = { 0 };
    vsbh.out       = out;
    vsbh.frame_ctx = NULL;
    vsbh.vsapi     = vsapi;
    /* Set up log handler. */
    lw_log_handler_t lh = { 0 };
    lh.level    = LW_LOG_FATAL;
    lh.priv     = &vsbh;
    lh.show_log = set_error;
    /* Get options. */
    int64_t stream_index;
    int64_t threads;
    int64_t cache_index;
    int64_t seek_mode;
    int64_t seek_threshold;
    int64_t variable_info;
    int64_t direct_rendering;
    int64_t fps_num;
    int64_t fps_den;
    int64_t apply_repeat_flag;
    int64_t field_dominance;
    const char *format;
    const char *preferred_decoder_names;
    set_option_int64 ( &stream_index,           -1,    "stream_index",   in, vsapi );
    set_option_int64 ( &threads,                 0,    "threads",        in, vsapi );
    set_option_int64 ( &cache_index,             1,    "cache",          in, vsapi );
    set_option_int64 ( &seek_mode,               0,    "seek_mode",      in, vsapi );
    set_option_int64 ( &seek_threshold,          10,   "seek_threshold", in, vsapi );
    set_option_int64 ( &variable_info,           0,    "variable",       in, vsapi );
    set_option_int64 ( &direct_rendering,        0,    "dr",             in, vsapi );
    set_option_int64 ( &fps_num,                 0,    "fpsnum",         in, vsapi );
    set_option_int64 ( &fps_den,                 1,    "fpsden",         in, vsapi );
    set_option_int64 ( &apply_repeat_flag,       0,    "repeat",         in, vsapi );
    set_option_int64 ( &field_dominance,         0,    "dominance",      in, vsapi );
    set_option_string( &format,                  NULL, "format",         in, vsapi );
    set_option_string( &preferred_decoder_names, NULL, "decoder",        in, vsapi );
    set_preferred_decoder_names_on_buf( hp->preferred_decoder_names_buf, preferred_decoder_names );
    /* Set options. */
    lwlibav_option_t opt;
    opt.file_path         = file_path;
    opt.threads           = threads >= 0 ? threads : 0;
    opt.av_sync           = 0;
    opt.no_create_index   = !cache_index;
    opt.force_video       = (stream_index >= 0);
    opt.force_video_index = stream_index >= 0 ? stream_index : -1;
    opt.force_audio       = 0;
    opt.force_audio_index = -1;
    opt.apply_repeat_flag = apply_repeat_flag;
    opt.field_dominance   = CLIP_VALUE( field_dominance, 0, 2 );    /* 0: Obey source flags, 1: TFF, 2: BFF */
    opt.vfr2cfr.active    = fps_num > 0 && fps_den > 0 ? 1 : 0;
    opt.vfr2cfr.fps_num   = fps_num;
    opt.vfr2cfr.fps_den   = fps_den;
    lwlibav_video_set_seek_mode              ( vdhp, CLIP_VALUE( seek_mode,      0, 2 ) );
    lwlibav_video_set_forward_seek_threshold ( vdhp, CLIP_VALUE( seek_threshold, 1, 999 ) );
    lwlibav_video_set_preferred_decoder_names( vdhp, tokenize_preferred_decoder_names( hp->preferred_decoder_names_buf ) );
    vs_vohp->variable_info          = CLIP_VALUE( variable_info,     0, 1 );
    vs_vohp->direct_rendering       = CLIP_VALUE( direct_rendering,  0, 1 ) && !format;
    vs_vohp->vs_output_pixel_format = vs_vohp->variable_info ? pfNone : get_vs_output_pixel_format( format );
    /* Set up progress indicator. */
    progress_indicator_t indicator;
    indicator.open   = NULL;
    indicator.update = NULL;
    indicator.close  = NULL;
    /* Construct index. */
    int ret = lwlibav_construct_index( lwhp, vdhp, vohp, hp->adhp, hp->aohp, &lh, &opt, &indicator, NULL );
    lwlibav_audio_free_decode_handler_ptr( &hp->adhp );
    lwlibav_audio_free_output_handler_ptr( &hp->aohp );
    if( ret < 0 )
    {
        vs_filter_free( hp, core, vsapi );
        set_error_on_init( out, vsapi, "lsmas: failed to construct index." );
        return;
    }
    /* Get the desired video track. */
    lwlibav_video_set_log_handler( vdhp, &lh );
    if( lwlibav_video_get_desired_track( lwhp->file_path, vdhp, lwhp->threads ) < 0 )
    {
        vs_filter_free( hp, core, vsapi );
        return;
    }
    /* Set average framerate. */
    hp->vi.numFrames = vohp->frame_count;
    hp->vi.fpsNum    = 25;
    hp->vi.fpsDen    = 1;
    lwlibav_video_setup_timestamp_info( lwhp, vdhp, vohp, &hp->vi.fpsNum, &hp->vi.fpsDen );
    /* Set up decoders for this stream. */
    if( prepare_video_decoding( hp, out, core, vsapi ) < 0 )
    {
        vs_filter_free( hp, core, vsapi );
        return;
    }
    vsapi->createFilter( in, out, "LWLibavSource", vs_filter_init, vs_filter_get_frame, vs_filter_free, fmUnordered, nfMakeLinear, hp, core );
    return;
}