Exemplo n.º 1
0
/**
 * It returns the format (closest to chroma) that can be converted to target */
static const d3d_format_t *Direct3DFindFormat(vout_display_t *vd, vlc_fourcc_t chroma, D3DFORMAT target)
{
    vout_display_sys_t *sys = vd->sys;

    for (unsigned pass = 0; pass < 2; pass++) {
        const vlc_fourcc_t *list;

        if (pass == 0 && sys->allow_hw_yuv && vlc_fourcc_IsYUV(chroma))
            list = vlc_fourcc_GetYUVFallback(chroma);
        else if (pass == 1)
            list = vlc_fourcc_GetRGBFallback(chroma);
        else
            continue;

        for (unsigned i = 0; list[i] != 0; i++) {
            for (unsigned j = 0; d3d_formats[j].name; j++) {
                const d3d_format_t *format = &d3d_formats[j];

                if (format->fourcc != list[i])
                    continue;

                msg_Warn(vd, "trying surface pixel format: %s",
                         format->name);
                if (!Direct3DCheckConversion(vd, format->format, target)) {
                    msg_Dbg(vd, "selected surface pixel format is %s",
                            format->name);
                    return format;
                }
            }
        }
    }
    return NULL;
}
Exemplo n.º 2
0
static int DirectXCreatePictureResource(vout_display_t *vd,
                                        bool *use_overlay,
                                        video_format_t *fmt)
{
    vout_display_sys_t *sys = vd->sys;

    /* */
    picture_sys_t *picsys = calloc(1, sizeof(*picsys));
    if (unlikely(picsys == NULL))
        return VLC_ENOMEM;
    sys->picsys = picsys;

    /* */
    bool allow_hw_yuv  = sys->can_blit_fourcc &&
                         vlc_fourcc_IsYUV(fmt->i_chroma) &&
                         var_InheritBool(vd, "directx-hw-yuv");
    bool allow_overlay = var_InheritBool(vd, "directx-overlay");

    /* Try to use an yuv surface */
    if (allow_hw_yuv) {
        const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma);
        /*  Try with overlay first */
        for (unsigned pass = allow_overlay ? 0 : 1; pass < 2; pass++) {
            for (unsigned i = 0; list[i] != 0; i++) {
                const DWORD fourcc = DirectXGetFourcc(list[i]);
                if (!fourcc)
                    continue;

                if (pass == 0) {
                    if (DirectXCreatePictureResourceYuvOverlay(vd, fmt, fourcc))
                    {
#ifndef NDEBUG
                        msg_Dbg(vd, "Failed to create YUV overlay surface %4.4s", (const char*)&fourcc);
#endif
                        continue;
                    }
                } else {
                    if (DirectXCreatePictureResourceYuv(vd, fmt, fourcc))
                    {
#ifndef NDEBUG
                        msg_Dbg(vd, "Failed to create YUV surface %4.4s", (const char*)&fourcc);
#endif
                        continue;
                    }
                }
                /* */
                *use_overlay = pass == 0;
                fmt->i_chroma = list[i];
                return VLC_SUCCESS;
            }
        }
    }

    /* Try plain RGB */
    return DirectXCreatePictureResourceRgb(vd, fmt);
}
Exemplo n.º 3
0
static int DirectXCreatePictureResource(vout_display_t *vd,
                                        bool *use_overlay,
                                        video_format_t *fmt)
{
    vout_display_sys_t *sys = vd->sys;

    /* */
    picture_resource_t *rsc = &sys->resource;
    rsc->p_sys = calloc(1, sizeof(*rsc->p_sys));
    if (!rsc->p_sys)
        return VLC_ENOMEM;

    /* */
    bool allow_hw_yuv  = sys->can_blit_fourcc &&
                         vlc_fourcc_IsYUV(fmt->i_chroma) &&
                         var_InheritBool(vd, "directx-hw-yuv");
    bool allow_overlay = var_InheritBool(vd, "overlay");

    /* Try to use an yuv surface */
    if (allow_hw_yuv) {
        const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma);
        /*  Try with overlay first */
        for (unsigned pass = allow_overlay ? 0 : 1; pass < 2; pass++) {
            for (unsigned i = 0; list[i] != 0; i++) {
                const DWORD fourcc = DirectXGetFourcc(list[i]);
                if (!fourcc)
                    continue;

                if (pass == 0) {
                    if (DirectXCreatePictureResourceYuvOverlay(vd, fmt, fourcc))
                        continue;
                } else {
                    if (DirectXCreatePictureResourceYuv(vd, fmt, fourcc))
                        continue;
                }
                /* */
                *use_overlay = pass == 0;
                fmt->i_chroma = list[i];
                return VLC_SUCCESS;
            }
        }
    }

    /* Try plain RGB */
    return DirectXCreatePictureResourceRgb(vd, fmt);
}
Exemplo n.º 4
0
/**
 * This function initializes SDL vout method.
 */
static int Open(vlc_object_t *object)
{
    vout_display_t *vd = (vout_display_t *)object;
    vout_display_sys_t *sys;

    /* XXX: check for conflicts with the SDL audio output */
    vlc_mutex_lock(&sdl_lock);

    /* Check if SDL video module has been initialized */
    if (SDL_WasInit(SDL_INIT_VIDEO) != 0) {
        vlc_mutex_unlock(&sdl_lock);
        return VLC_EGENERIC;
    }

    vd->sys = sys = calloc(1, sizeof(*sys));
    if (!sys) {
        vlc_mutex_unlock(&sdl_lock);
        return VLC_ENOMEM;
    }

#ifdef HAVE_SETENV
    char *psz_driver = var_CreateGetNonEmptyString(vd, "sdl-video-driver");
    if (psz_driver) {
        setenv("SDL_VIDEODRIVER", psz_driver, 1);
        free(psz_driver);
    }
#endif

    /* */
    int sdl_flags = SDL_INIT_VIDEO;
#ifndef WIN32
    /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
    sdl_flags |= SDL_INIT_EVENTTHREAD;
#endif
#ifndef NDEBUG
    /* In debug mode you may want vlc to dump a core instead of staying stuck */
    sdl_flags |= SDL_INIT_NOPARACHUTE;
#endif

    /* Initialize library */
    if (SDL_Init(sdl_flags) < 0) {
        vlc_mutex_unlock(&sdl_lock);

        msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError());
        free(sys);
        return VLC_EGENERIC;
    }
    vlc_mutex_unlock(&sdl_lock);

    /* Translate keys into unicode */
    SDL_EnableUNICODE(1);

    /* Get the desktop resolution */
    /* FIXME: SDL has a problem with virtual desktop */
    sys->desktop_width  = SDL_GetVideoInfo()->current_w;
    sys->desktop_height = SDL_GetVideoInfo()->current_h;

    /* */
    video_format_t fmt = vd->fmt;

    /* */
    vout_display_info_t info = vd->info;

    /* Set main window's size */
    int display_width;
    int display_height;
    if (vd->cfg->is_fullscreen) {
        display_width  = sys->desktop_width;
        display_height = sys->desktop_height;
    } else {
        display_width  = vd->cfg->display.width;
        display_height = vd->cfg->display.height;
    }

    /* Initialize flags and cursor */
    sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
    sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;

    sys->display_bpp = SDL_VideoModeOK(display_width, display_height,
                                       16, sys->display_flags);
    if (sys->display_bpp == 0) {
        msg_Err(vd, "no video mode available");
        goto error;
    }

    sys->display = SDL_SetVideoMode(display_width, display_height,
                                    sys->display_bpp, sys->display_flags);
    if (!sys->display) {
        msg_Err(vd, "cannot set video mode");
        goto error;
    }

    /* We keep the surface locked forever */
    SDL_LockSurface(sys->display);

    /* */
    vlc_fourcc_t forced_chroma = 0;
    char *psz_chroma = var_CreateGetNonEmptyString(vd, "sdl-chroma");
    if (psz_chroma) {
        forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma);
        if (forced_chroma)
            msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)",
                    forced_chroma, (const char*)&forced_chroma);
        free(psz_chroma);
    }

    /* Try to open an overlay if requested */
    sys->overlay = NULL;
    const bool is_overlay = var_CreateGetBool(vd, "overlay");
    if (is_overlay) {
        static const struct
        {
            vlc_fourcc_t vlc;
            uint32_t     sdl;
        } vlc_to_sdl[] = {
            { VLC_CODEC_YV12, SDL_YV12_OVERLAY },
            { VLC_CODEC_I420, SDL_IYUV_OVERLAY },
            { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY },
            { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY },
            { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY },

            { 0, 0 }
        };
        const vlc_fourcc_t forced_chromas[] = {
            forced_chroma, 0
        };
        const vlc_fourcc_t *fallback_chromas =
            vlc_fourcc_GetYUVFallback(fmt.i_chroma);
        const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas;

        for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) {
            for (int i = 0; chromas[i] != 0; i++) {
                const vlc_fourcc_t vlc = chromas[i];

                uint32_t sdl = 0;
                for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) {
                    if (vlc_to_sdl[j].vlc == vlc)
                        sdl = vlc_to_sdl[j].sdl;
                }
                if (!sdl)
                    continue;

                sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height,
                                                    sdl, sys->display);
                if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) {
                    /* Ignore non hardware overlay surface in first pass */
                    SDL_FreeYUVOverlay(sys->overlay);
                    sys->overlay = NULL;
                }
                if (sys->overlay) {
                    /* We keep the surface locked forever */
                    SDL_LockYUVOverlay(sys->overlay);

                    fmt.i_chroma = vlc;
                    sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma,
                                                                       vd->fmt.i_chroma);
                    if (sys->is_uv_swapped)
                        fmt.i_chroma = vd->fmt.i_chroma;
                    break;
                }
            }
        }
    } else {
        msg_Warn(vd, "SDL overlay disabled by the user");
    }

    /* */
    vout_display_cfg_t place_cfg = *vd->cfg;
    place_cfg.display.width  = display_width;
    place_cfg.display.height = display_height;
    vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay);

    /* If no overlay, fallback to software output */
    if (!sys->overlay) {
        /* */
        switch (sys->display->format->BitsPerPixel) {
        case 8:
            fmt.i_chroma = VLC_CODEC_RGB8;
            break;
        case 15:
            fmt.i_chroma = VLC_CODEC_RGB15;
            break;
        case 16:
            fmt.i_chroma = VLC_CODEC_RGB16;
            break;
        case 24:
            fmt.i_chroma = VLC_CODEC_RGB24;
            break;
        case 32:
            fmt.i_chroma = VLC_CODEC_RGB32;
            break;
        default:
            msg_Err(vd, "unknown screen depth %i",
                    sys->display->format->BitsPerPixel);
            goto error;
        }

        /* All we have is an RGB image with square pixels */
        fmt.i_width  = display_width;
        fmt.i_height = display_height;
        fmt.i_rmask = sys->display->format->Rmask;
        fmt.i_gmask = sys->display->format->Gmask;
        fmt.i_bmask = sys->display->format->Bmask;

        info.has_pictures_invalid = true;
    }

    if (vd->cfg->display.title)
        SDL_WM_SetCaption(vd->cfg->display.title,
                          vd->cfg->display.title);
    else if (!sys->overlay)
        SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)",
                          VOUT_TITLE " (software RGB SDL output)");
    else if (sys->overlay->hw_overlay)
        SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)",
                          VOUT_TITLE " (hardware YUV SDL output)");
    else
        SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)",
                          VOUT_TITLE " (software YUV SDL output)");

    /* Setup events */
    SDL_EventState(SDL_KEYUP, SDL_IGNORE);               /* ignore keys up */

    /* Setup vout_display now that everything is fine */
    vd->fmt = fmt;
    vd->info = info;

    vd->get     = Get;
    vd->prepare = NULL;
    vd->display = Display;
    vd->control = Control;
    vd->manage  = Manage;

    /* */
    vout_display_SendEventDisplaySize(vd, display_width, display_height, vd->cfg->is_fullscreen);
    return VLC_SUCCESS;

error:
    msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError());

    if (sys->display) {
        SDL_UnlockSurface(sys->display);
        SDL_FreeSurface(sys->display);
    }

    vlc_mutex_lock(&sdl_lock);
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
    vlc_mutex_unlock(&sdl_lock);

    free(sys);
    return VLC_EGENERIC;
}
Exemplo n.º 5
0
/*****************************************************************************
 * OpenDisplay: open and initialize KVA device
 *****************************************************************************
 * Open and initialize display according to preferences specified in the vout
 * thread fields.
 *****************************************************************************/
static int OpenDisplay( vout_display_t *vd, video_format_t *fmt )
{
    vout_display_sys_t * sys = vd->sys;
    const vlc_fourcc_t *fallback;
    bool b_hw_accel = 0;
    FOURCC i_kva_fourcc;
    int i_chroma_shift;
    char sz_title[ 256 ];
    RECTL rcl;
    int w, h;

    msg_Dbg( vd, "render chroma = %4.4s", ( const char * )&fmt->i_chroma );

    for( int pass = 0; pass < 2 && !b_hw_accel; pass++ )
    {
        fallback = ( pass == 0 ) ? vlc_fourcc_GetYUVFallback( fmt->i_chroma ) :
                   vlc_fourcc_GetRGBFallback( fmt->i_chroma );

        for( int i = 0; fallback[ i ]; i++ )
        {
            switch( fallback[ i ])
            {
            case VLC_CODEC_YV12:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YV12;
                i_kva_fourcc = FOURCC_YV12;
                i_chroma_shift = 1;
                break;

            case VLC_CODEC_YUYV:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YUY2;
                i_kva_fourcc = FOURCC_Y422;
                i_chroma_shift = 0;
                break;

            case VLC_CODEC_YV9:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YVU9;
                i_kva_fourcc = FOURCC_YVU9;
                i_chroma_shift = 2;
                break;

            case VLC_CODEC_RGB32:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR32;
                i_kva_fourcc = FOURCC_BGR4;
                i_chroma_shift = 0;
                break;

            case VLC_CODEC_RGB24:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR24;
                i_kva_fourcc = FOURCC_BGR3;
                i_chroma_shift = 0;
                break;

            case VLC_CODEC_RGB16:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR16;
                i_kva_fourcc = FOURCC_R565;
                i_chroma_shift = 0;
                break;

            case VLC_CODEC_RGB15:
                b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR15;
                i_kva_fourcc = FOURCC_R555;
                i_chroma_shift = 0;
                break;
            }

            if( b_hw_accel )
            {
                fmt->i_chroma = fallback[ i ];
                break;
            }
        }
    }

    if( !b_hw_accel )
    {
        msg_Err( vd, "Ooops. There is no fourcc supported by KVA at all.");

        return VLC_EGENERIC;
    }

    /* Set the RGB masks */
    fmt->i_rmask = sys->kvac.ulRMask;
    fmt->i_gmask = sys->kvac.ulGMask;
    fmt->i_bmask = sys->kvac.ulBMask;

    msg_Dbg( vd, "output chroma = %4.4s", ( const char * )&fmt->i_chroma );
    msg_Dbg( vd, "KVA chroma = %4.4s", ( const char * )&i_kva_fourcc );

    w = vd->source.i_width;
    h = vd->source.i_height;

    sys->kvas.ulLength           = sizeof( KVASETUP );
    sys->kvas.szlSrcSize.cx      = w;
    sys->kvas.szlSrcSize.cy      = h;
    sys->kvas.rclSrcRect.xLeft   = 0;
    sys->kvas.rclSrcRect.yTop    = 0;
    sys->kvas.rclSrcRect.xRight  = w;
    sys->kvas.rclSrcRect.yBottom = h;
    sys->kvas.ulRatio            = KVAR_FORCEANY;
    sys->kvas.ulAspectWidth      = w;
    sys->kvas.ulAspectHeight     = h;
    sys->kvas.fccSrcColor        = i_kva_fourcc;
    sys->kvas.fDither            = TRUE;

    if( kvaSetup( &sys->kvas ))
    {
        msg_Err( vd, "cannot set up KVA");

        return VLC_EGENERIC;
    }

    /* Create the associated picture */
    picture_resource_t *rsc = &sys->resource;
    rsc->p_sys = malloc( sizeof( *rsc->p_sys ));
    if( !rsc->p_sys )
        return VLC_EGENERIC;

    rsc->p_sys->i_chroma_shift = i_chroma_shift;

    for( int i = 0; i < PICTURE_PLANE_MAX; i++ )
    {
        rsc->p[ i ].p_pixels = NULL;
        rsc->p[ i ].i_pitch  = 0;
        rsc->p[ i ].i_lines  = 0;
    }

    picture_t *picture = picture_NewFromResource( fmt, rsc );
    if( !picture )
        goto exit_picture;

    /* Wrap it into a picture pool */
    picture_pool_configuration_t pool_cfg;
    memset( &pool_cfg, 0, sizeof( pool_cfg ));
    pool_cfg.picture_count = 1;
    pool_cfg.picture       = &picture;
    pool_cfg.lock          = KVALock;
    pool_cfg.unlock        = KVAUnlock;

    sys->pool = picture_pool_NewExtended( &pool_cfg );
    if( !sys->pool )
    {
        picture_Release( picture );

        goto exit_picture;
    }

    if (vd->cfg->display.title)
        snprintf( sz_title, sizeof( sz_title ), "%s", vd->cfg->display.title );
    else
        snprintf( sz_title, sizeof( sz_title ),
                  "%s (%4.4s to %4.4s - %s mode KVA output)",
                  VOUT_TITLE,
                  ( char * )&vd->fmt.i_chroma,
                  ( char * )&sys->kvas.fccSrcColor,
                  psz_video_mode[ sys->kvac.ulMode - 1 ]);
    WinSetWindowText( sys->frame, sz_title );

    sys->i_screen_width  = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
    sys->i_screen_height = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );

    if( sys->parent_window )
        WinQueryWindowRect( sys->parent, &sys->client_rect );
    else
    {
        sys->client_rect.xLeft   = ( sys->i_screen_width  - w ) / 2;
        sys->client_rect.yBottom = ( sys->i_screen_height - h ) / 2 ;
        sys->client_rect.xRight  = sys->client_rect.xLeft   + w;
        sys->client_rect.yTop    = sys->client_rect.yBottom + h;
    }

    rcl = sys->client_rect;

    WinCalcFrameRect( sys->frame, &rcl, FALSE);

    WinSetWindowPos( sys->frame, HWND_TOP,
                     rcl.xLeft, rcl.yBottom,
                     rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom,
                     SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW |
                     SWP_ACTIVATE );

    return VLC_SUCCESS;

exit_picture:
    free( rsc->p_sys );

    return VLC_EGENERIC;
}