Beispiel #1
0
/*****************************************************************************
 * Open: allocates Wall video thread output method
 *****************************************************************************
 * This function allocates and initializes a Wall vout method.
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    video_splitter_t *p_splitter = (video_splitter_t*)p_this;
    video_splitter_sys_t *p_sys;

    const panoramix_chroma_t *p_chroma;
    for( int i = 0; ; i++ )
    {
        vlc_fourcc_t i_chroma = p_chroma_array[i].i_chroma;
        if( !i_chroma )
        {
            msg_Err( p_splitter, "colorspace not supported by plug-in !" );
            return VLC_EGENERIC;
        }
        if( i_chroma == p_splitter->fmt.i_chroma )
        {
            p_chroma = &p_chroma_array[i];
            break;
        }
    }

    /* Allocate structure */
    p_splitter->p_sys = p_sys = malloc( sizeof( *p_sys ) );
    if( !p_sys )
        return VLC_ENOMEM;

    /* */
    p_sys->p_chroma = p_chroma;

    /* */
    config_ChainParse( p_splitter, CFG_PREFIX, ppsz_filter_options,
                       p_splitter->p_cfg );

    /* */
    p_sys->i_col = var_InheritInteger( p_splitter, CFG_PREFIX "cols" );
    p_sys->i_row = var_InheritInteger( p_splitter, CFG_PREFIX "rows" );

    /* Autodetect number of displays */
    if( p_sys->i_col < 0 || p_sys->i_row < 0 )
    {
#ifdef WIN32
        const int i_monitor_count = GetSystemMetrics(SM_CMONITORS);
        if( i_monitor_count > 1 )
        {
            p_sys->i_col = GetSystemMetrics( SM_CXVIRTUALSCREEN ) / GetSystemMetrics( SM_CXSCREEN );
            p_sys->i_row = GetSystemMetrics( SM_CYVIRTUALSCREEN ) / GetSystemMetrics( SM_CYSCREEN );
            if( p_sys->i_col * p_sys->i_row != i_monitor_count )
            {
                p_sys->i_col = i_monitor_count;
                p_sys->i_row = 1;
            }
        }
#else
        const unsigned i_monitors = CountMonitors( p_this );
        if( i_monitors > 1 ) /* Find closest to square */
            for( unsigned w = 1; (i_monitors / w) >= w ; w++ )
            {
                if( i_monitors % w )
                    continue;
                p_sys->i_row = w;
                p_sys->i_col = i_monitors / w;
            }
#endif
        /* By default do 2x1 */
        if( p_sys->i_row < 0 )
            p_sys->i_row = 1;
        if( p_sys->i_col < 0 )
            p_sys->i_col = 2;
        var_SetInteger( p_splitter, CFG_PREFIX "cols", p_sys->i_col);
        var_SetInteger( p_splitter, CFG_PREFIX "rows", p_sys->i_row);
    }

    /* */
    p_sys->b_attenuate = var_InheritBool( p_splitter, CFG_PREFIX "attenuate");
    p_sys->bz_length = var_InheritInteger( p_splitter, CFG_PREFIX "bz-length" );
    p_sys->bz_height = var_InheritInteger( p_splitter, CFG_PREFIX "bz-height" );
    p_sys->bz_begin = var_InheritInteger( p_splitter, CFG_PREFIX "bz-begin" );
    p_sys->bz_middle = var_InheritInteger( p_splitter, CFG_PREFIX "bz-middle" );
    p_sys->bz_end = var_InheritInteger( p_splitter, CFG_PREFIX "bz-end" );
    p_sys->bz_middle_pos = var_InheritInteger( p_splitter, CFG_PREFIX "bz-middle-pos" );
    double d_p = 100.0 / p_sys->bz_middle_pos;

    p_sys->a_2 = d_p * p_sys->bz_begin - (double)(d_p * d_p / (d_p - 1)) * p_sys->bz_middle + (double)(d_p / (d_p - 1)) * p_sys->bz_end;
    p_sys->a_1 = -(d_p + 1) * p_sys->bz_begin + (double)(d_p * d_p / (d_p - 1)) * p_sys->bz_middle - (double)(1 / (d_p - 1)) * p_sys->bz_end;
    p_sys->a_0 =  p_sys->bz_begin;

    /* */
    p_sys->i_col = VLC_CLIP( COL_MAX, 1, p_sys->i_col );
    p_sys->i_row = VLC_CLIP( ROW_MAX, 1, p_sys->i_row );
    msg_Dbg( p_splitter, "opening a %i x %i wall",
             p_sys->i_col, p_sys->i_row );

    if( p_sys->bz_length > 0 && ( p_sys->i_row > 1 || p_sys->i_col > 1 ) )
    {
        const int i_overlap_w2_max = p_splitter->fmt.i_width  / p_sys->i_col / 2;
        const int i_overlap_h2_max = p_splitter->fmt.i_height / p_sys->i_row / 2;
        const int i_overlap2_max = __MIN( i_overlap_w2_max, i_overlap_h2_max );

        if( p_sys->i_col > 1 )
            p_sys->i_overlap_w2 = i_overlap2_max * p_sys->bz_length / 100;
        else
            p_sys->i_overlap_w2 = 0;

        if( p_sys->i_row > 1 )
            p_sys->i_overlap_h2 = i_overlap2_max * p_sys->bz_height / 100;
        else
            p_sys->i_overlap_h2 = 0;

        /* */
        int i_div_max_w = 1;
        int i_div_max_h = 1;
        for( int i = 0; i < VOUT_MAX_PLANES; i++ )
        {
            i_div_max_w = __MAX( i_div_max_w, p_chroma->pi_div_w[i] );
            i_div_max_h = __MAX( i_div_max_h, p_chroma->pi_div_h[i] );
        }
        p_sys->i_overlap_w2 = i_div_max_w * (p_sys->i_overlap_w2 / i_div_max_w);
        p_sys->i_overlap_h2 = i_div_max_h * (p_sys->i_overlap_h2 / i_div_max_h);
    }
    else
    {
        p_sys->i_overlap_w2 = 0;
        p_sys->i_overlap_h2 = 0;
    }

    /* Compute attenuate parameters */
    if( p_sys->b_attenuate )
    {
        panoramix_gamma_t p_gamma[VOUT_MAX_PLANES];

        p_gamma[0].f_gamma = var_InheritFloat( p_splitter, CFG_PREFIX "bz-gamma-red" );
        p_gamma[1].f_gamma = var_InheritFloat( p_splitter, CFG_PREFIX "bz-gamma-green" );
        p_gamma[2].f_gamma = var_InheritFloat( p_splitter, CFG_PREFIX "bz-gamma-blue" );

        p_gamma[0].f_black_crush = var_InheritInteger( p_splitter, CFG_PREFIX "bz-blackcrush-red" ) / 255.0;
        p_gamma[1].f_black_crush = var_InheritInteger( p_splitter, CFG_PREFIX "bz-blackcrush-green" ) / 255.0;
        p_gamma[2].f_black_crush = var_InheritInteger( p_splitter, CFG_PREFIX "bz-blackcrush-blue" ) / 255.0;
        p_gamma[0].f_white_crush = var_InheritInteger( p_splitter, CFG_PREFIX "bz-whitecrush-red" ) / 255.0;
        p_gamma[1].f_white_crush = var_InheritInteger( p_splitter, CFG_PREFIX "bz-whitecrush-green" ) / 255.0;
        p_gamma[2].f_white_crush = var_InheritInteger( p_splitter, CFG_PREFIX "bz-whitecrush-blue" ) / 255.0;

        p_gamma[0].f_black_level = var_InheritInteger( p_splitter, CFG_PREFIX "bz-blacklevel-red" ) / 255.0;
        p_gamma[1].f_black_level = var_InheritInteger( p_splitter, CFG_PREFIX "bz-blacklevel-green" ) / 255.0;
        p_gamma[2].f_black_level = var_InheritInteger( p_splitter, CFG_PREFIX "bz-blacklevel-blue" ) / 255.0;
        p_gamma[0].f_white_level = var_InheritInteger( p_splitter, CFG_PREFIX "bz-whitelevel-red" ) / 255.0;
        p_gamma[1].f_white_level = var_InheritInteger( p_splitter, CFG_PREFIX "bz-whitelevel-green" ) / 255.0;
        p_gamma[2].f_white_level = var_InheritInteger( p_splitter, CFG_PREFIX "bz-whitelevel-blue" ) / 255.0;

        for( int i = 3; i < VOUT_MAX_PLANES; i++ )
        {
            /* Initialize unsupported planes */
            p_gamma[i].f_gamma = 1.0;
            p_gamma[i].f_black_crush = 140.0/255.0;
            p_gamma[i].f_white_crush = 200.0/255.0;
            p_gamma[i].f_black_level = 150.0/255.0;
            p_gamma[i].f_white_level = 0.0/255.0;
        }

        if( p_chroma->i_chroma == VLC_CODEC_YV12 )
        {
            /* Exchange U and V */
            panoramix_gamma_t t = p_gamma[1];
            p_gamma[1] = p_gamma[2];
            p_gamma[2] = t;
        }

        for( int i_index = 0; i_index < 256; i_index++ )
        {
            for( int i_index2 = 0; i_index2 <= ACCURACY; i_index2++ )
            {
                for( int i_plane = 0; i_plane < VOUT_MAX_PLANES; i_plane++ )
                {
                    double f_factor = GammaFactor( &p_gamma[i_plane], (float)i_index / 255.0 );

                    float f_lut = clip_unit( 1.0 - ((ACCURACY - (float)i_index2) * f_factor / (ACCURACY - 1)) );

                    p_sys->p_lut[i_plane][i_index2][i_index] = f_lut * i_index + (int)( (1.0 - f_lut) * (float)p_chroma->pi_black[i_plane] );
                }
            }
        }

        for( int i_plane = 0; i_plane < VOUT_MAX_PLANES; i_plane++ )
        {
            if( !p_chroma->pi_div_w[i_plane] || !p_chroma->pi_div_h[i_plane] )
                continue;
            const int i_length_w = (2 * p_sys->i_overlap_w2) / p_chroma->pi_div_w[i_plane];
            const int i_length_h = (2 * p_sys->i_overlap_h2) / p_chroma->pi_div_h[i_plane];

            for( int i_dir = 0; i_dir < 2; i_dir++ )
            {
                const int i_length = i_dir == 0 ? i_length_w : i_length_h;
                const int i_den = i_length * i_length;
                const int a_2 = p_sys->a_2 * (ACCURACY / 100);
                const int a_1 = p_sys->a_1 * i_length * (ACCURACY / 100);
                const int a_0 = p_sys->a_0 * i_den * (ACCURACY / 100);

                for( int i_position = 0; i_position < 2; i_position++ )
                {
                    for( int i_index = 0; i_index < i_length; i_index++ )
                    {
                        const int v = i_position == 1 ? i_index : (i_length - i_index);
                        const int i_lambda = clip_accuracy( ACCURACY - (a_2 * v*v + a_1 * v + a_0) / i_den );

                        if( i_dir == 0 )
                            p_sys->lambdav[i_plane][i_position][i_index] = i_lambda;
                        else
                            p_sys->lambdah[i_plane][i_position][i_index] = i_lambda;
                    }
                }
            }
        }
    }

    /* */
    char *psz_state = var_InheritString( p_splitter, CFG_PREFIX "active" );

    /* */
    bool pb_active[COL_MAX*ROW_MAX];

    for( int i = 0; i < COL_MAX*ROW_MAX; i++ )
        pb_active[i] = psz_state == NULL;

    /* Parse active list if provided */
    char *psz_tmp = psz_state;
    while( psz_tmp && *psz_tmp )
    {
        char *psz_next = strchr( psz_tmp, ',' );
        if( psz_next )
            *psz_next++ = '\0';

        const int i_index = atoi( psz_tmp );
        if( i_index >= 0 && i_index < COL_MAX*ROW_MAX )
            pb_active[i_index] = true;

        psz_tmp = psz_next;
    }
    free( psz_state );

    /* */
    p_splitter->i_output =
        Configuration( p_sys->pp_output,
                       p_sys->i_col, p_sys->i_row,
                       p_splitter->fmt.i_width, p_splitter->fmt.i_height,
                       p_sys->i_overlap_w2, p_sys->i_overlap_h2,
                       p_sys->b_attenuate,
                       pb_active );
    p_splitter->p_output = calloc( p_splitter->i_output,
                                   sizeof(*p_splitter->p_output) );
    if( !p_splitter->p_output )
    {
        free( p_sys );
        return VLC_ENOMEM;
    }

    for( int y = 0; y < p_sys->i_row; y++ )
    {
        for( int x = 0; x < p_sys->i_col; x++ )
        {
            panoramix_output_t *p_output = &p_sys->pp_output[x][y];
            if( !p_output->b_active )
                continue;

            video_splitter_output_t *p_cfg = &p_splitter->p_output[p_output->i_output];

            /* */
            video_format_Copy( &p_cfg->fmt, &p_splitter->fmt );
            p_cfg->fmt.i_visible_width  =
            p_cfg->fmt.i_width          = p_output->i_width;
            p_cfg->fmt.i_visible_height =
            p_cfg->fmt.i_height         = p_output->i_height;

            p_cfg->window.i_x     = p_output->i_x;
            p_cfg->window.i_y     = p_output->i_y;
            p_cfg->window.i_align = p_output->i_align;

            p_cfg->psz_module = NULL;
        }
    }


    /* */
    p_splitter->pf_filter = Filter;
    p_splitter->pf_mouse  = Mouse;

    return VLC_SUCCESS;
}
// static
BOOL Devices::UpdateInstance(JNIEnv *env)
{
    J2dTraceLn(J2D_TRACE_INFO, "Devices::UpdateInstance");

    int numScreens = CountMonitors();
    HMONITOR *monHds = (HMONITOR *)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc,
            numScreens, sizeof(HMONITOR));
    if (numScreens != CollectMonitors(monHds, numScreens)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "Devices::UpdateInstance: Failed to get all "\
                      "monitor handles.");
        free(monHds);
        return FALSE;
    }

    Devices *newDevices = new Devices(numScreens);
    // This way we know that the array will not be disposed of
    // at least until we replaced it with a new one.
    newDevices->AddReference();

    // Create all devices first, then initialize them.  This allows
    // correct configuration of devices after contruction of the
    // primary device (which may not be device 0).
    AwtWin32GraphicsDevice** rawDevices = newDevices->GetRawArray();
    int i;
    for (i = 0; i < numScreens; ++i) {
        J2dTraceLn2(J2D_TRACE_VERBOSE, "  hmon[%d]=0x%x", i, monHds[i]);
        rawDevices[i] = new AwtWin32GraphicsDevice(i, monHds[i], newDevices);
    }
    for (i = 0; i < numScreens; ++i) {
        rawDevices[i]->Initialize();
    }
    {
        CriticalSection::Lock l(arrayLock);

        // install the new devices array
        Devices *oldDevices = theInstance;
        theInstance = newDevices;

        if (oldDevices) {
            // Invalidate the devices with indexes out of the new set of
            // devices. This doesn't cover all cases when the device
            // might should be invalidated (like if it's not the last device
            // that was removed), but it will have to do for now.
            int oldNumScreens = oldDevices->GetNumDevices();
            int newNumScreens = theInstance->GetNumDevices();
            J2dTraceLn(J2D_TRACE_VERBOSE, "  Invalidating removed devices");
            for (int i = newNumScreens; i < oldNumScreens; i++) {
                // removed device, needs to be invalidated
                J2dTraceLn1(J2D_TRACE_WARNING,
                            "Devices::UpdateInstance: device removed: %d", i);
                oldDevices->GetDevice(i)->Invalidate(env);
            }
            // Now that we have a new array in place, remove this (possibly the
            // last) reference to the old instance.
            oldDevices->Release();
        }
        D3DPipelineManager::HandleAdaptersChange((HMONITOR*)monHds,
                                                 theInstance->GetNumDevices());
    }
    free(monHds);

    return TRUE;
}