Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/doc/libvlc/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 16 kB image not shown  

Quelle  d3d9_player.c   Sprache: C

 

/* compile using: gcc d3d9_player.c -o d3d9_player.exe -I <path/liblc> -llibvlc -ld3d9 */

#include <windows.h>
#include <windowsx.h>
#define COBJMACROS
#include <d3d9.h>

#include <vlc/vlc.h>

#define SCREEN_WIDTH   900
#define SCREEN_HEIGHT  900
#define BORDER_LEFT    ( 20)
#define BORDER_RIGHT   (700 + BORDER_LEFT)
#define BORDER_TOP     ( 10)
#define BORDER_BOTTOM  (700 + BORDER_TOP)

struct render_context
{
    HWND hWnd;

    libvlc_media_player_t *p_mp;

    IDirect3D9Ex *d3d;
    IDirect3DDevice9 *d3ddev;     /* the host app device */
    IDirect3DDevice9 *libvlc_d3d; /* the device where VLC can do its rendering */

    /* surface we'll use to display on our backbuffer */
    IDirect3DTexture9 *renderTexture;
    HANDLE sharedHandled;
    /* surface that VLC will render to, which is a shared version of renderTexture
     * on libvlc_d3d                                                           */

    IDirect3DTexture9 *sharedRenderTexture;
    IDirect3DSurface9 *sharedRenderSurface;

    /* our swapchain backbuffer */
    IDirect3DSurface9 *backBuffer;

    IDirect3DVertexBuffer9 *rectangleFVFVertexBuf;

    CRITICAL_SECTION sizeLock; // the ReportSize callback cannot be called during/after the CleanupDevice_cb is called
    unsigned width, height;
    libvlc_video_output_resize_cb ReportSize;
    void *ReportOpaque;
};

struct CUSTOMVERTEX {FLOAT X, Y, Z, RHW; DWORD COLOR;
                     FLOAT tu, tv; /* texture relative coordinates */};
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)

/**
 * Callback called when it's time to display the video, in sync with the audio.
 *
 * This is called outside of the UI thread (in the VLC rendering thread).
 */

static void Swap(struct render_context *ctx)
{
    /* finished drawing to our swap surface, now render that surface to the backbuffer */
    IDirect3DDevice9_SetRenderTarget(ctx->d3ddev, 0, ctx->backBuffer);

    /* clear the backbuffer to orange */
    IDirect3DDevice9_Clear(ctx->d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 120, 0), 1.0f, 0);

    IDirect3DDevice9_BeginScene(ctx->d3ddev);
    IDirect3DDevice9_SetTexture(ctx->d3ddev, 0, (IDirect3DBaseTexture9*)ctx->renderTexture);

    IDirect3DDevice9_SetStreamSource(ctx->d3ddev, 0, ctx->rectangleFVFVertexBuf, 0, sizeof(struct CUSTOMVERTEX));
    IDirect3DDevice9_SetFVF(ctx->d3ddev, CUSTOMFVF);
    IDirect3DDevice9_DrawPrimitive(ctx->d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
    IDirect3DDevice9_EndScene(ctx->d3ddev);

    IDirect3DDevice9_Present(ctx->d3ddev, NULL, NULL, ctx->hWnd, NULL);
}

/**
 * Callback called to tell the size of the surface that should be available
 * to VLC to draw into.
 *
 * This is called outside of the UI thread (not the VLC rendering thread).
 */

static bool Resize(struct render_context *ctx, unsigned width, unsigned height,
                   IDirect3DDevice9 *vlc_device,
                   libvlc_video_output_cfg_t *out)
{
    HRESULT hr;
    D3DDISPLAYMODE d3ddm;

    hr = IDirect3D9Ex_GetAdapterDisplayMode(ctx->d3d, 0, &d3ddm);

    /* create the output surface VLC will write to */
    if (ctx->renderTexture)
    {
        IDirect3DTexture9_Release(ctx->renderTexture);
        ctx->renderTexture = NULL;
        ctx->sharedHandled = NULL;
    }
    if (ctx->sharedRenderTexture)
    {
        IDirect3DTexture9_Release(ctx->sharedRenderTexture);
        ctx->sharedRenderTexture = NULL;
    }
    if (ctx->sharedRenderSurface)
    {
        IDirect3DSurface9_Release(ctx->sharedRenderSurface);
        ctx->sharedRenderSurface = NULL;
    }
    /* the device to use may have changed */
    if (ctx->libvlc_d3d)
    {
        IDirect3DDevice9_Release(ctx->libvlc_d3d);
    }
    ctx->libvlc_d3d = vlc_device;
    IDirect3DDevice9_AddRef(ctx->libvlc_d3d);

    /* texture we can use on our device */
    hr = IDirect3DDevice9_CreateTexture(ctx->d3ddev, width, height, 1, D3DUSAGE_RENDERTARGET,
                                        d3ddm.Format,
                                        D3DPOOL_DEFAULT,
                                        &ctx->renderTexture,
                                        &ctx->sharedHandled);
    if (FAILED(hr))
        return false;

    /* texture/surface that is set as the render target for libvlc on its device */
    hr = IDirect3DDevice9_CreateTexture(ctx->libvlc_d3d, width, height, 1, D3DUSAGE_RENDERTARGET,
                                        d3ddm.Format,
                                        D3DPOOL_DEFAULT,
                                        &ctx->sharedRenderTexture,
                                        &ctx->sharedHandled);
    if (FAILED(hr))
        return false;

    hr = IDirect3DTexture9_GetSurfaceLevel(ctx->sharedRenderTexture, 0, &ctx->sharedRenderSurface);
    if (FAILED(hr))
        return false;

    hr = IDirect3DDevice9_SetRenderTarget(ctx->libvlc_d3d, 0, ctx->sharedRenderSurface);
    if (FAILED(hr)) return false;

    out->u.d3d9_format    = d3ddm.Format;
    out->full_range     = true;
    out->colorspace     = libvlc_video_colorspace_BT709;
    out->primaries      = libvlc_video_primaries_BT709;
    out->transfer       = libvlc_video_transfer_func_SRGB;
    out->orientation    = libvlc_video_orient_top_left;

    return true;
}

static void init_direct3d(struct render_context *ctx, HWND hWnd)
{
    ctx->hWnd = hWnd;
    HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &ctx->d3d);

    D3DPRESENT_PARAMETERS d3dpp = { 0 };
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;

    IDirect3D9Ex_CreateDevice(ctx->d3d, D3DADAPTER_DEFAULT,
                            D3DDEVTYPE_HAL,
                            NULL,
                            D3DCREATE_MULTITHREADED| D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
                            &d3dpp,
                            &ctx->d3ddev);

    IDirect3DDevice9_GetRenderTarget(ctx->d3ddev, 0, &ctx->backBuffer);

    struct CUSTOMVERTEX rectangleVertices[] =
    {
        {  BORDER_LEFT,    BORDER_TOP, 0.0f, 1.0f, D3DCOLOR_ARGB(255, 255, 255, 255), 0.0f, 0.0f },
        { BORDER_RIGHT,    BORDER_TOP, 0.0f, 1.0f, D3DCOLOR_ARGB(255, 255, 255, 255), 1.0f, 0.0f },
        { BORDER_RIGHT, BORDER_BOTTOM, 0.0f, 1.0f, D3DCOLOR_ARGB(255, 255, 255, 255), 1.0f, 1.0f },
        {  BORDER_LEFT, BORDER_BOTTOM, 0.0f, 1.0f, D3DCOLOR_ARGB(255, 255, 255, 255), 0.0f, 1.0f },
    };
    IDirect3DDevice9Ex_CreateVertexBuffer(ctx->d3ddev, sizeof(rectangleVertices),
                                        D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
                                        CUSTOMFVF,
                                        D3DPOOL_DEFAULT,
                                        &ctx->rectangleFVFVertexBuf,
                                        NULL);

    LPVOID pVoid;
    IDirect3DVertexBuffer9_Lock(ctx->rectangleFVFVertexBuf, 0, 0, (void**)&pVoid, 0);
    memcpy(pVoid, rectangleVertices, sizeof(rectangleVertices));
    IDirect3DVertexBuffer9_Unlock(ctx->rectangleFVFVertexBuf);
}

static void release_direct3d(struct render_context *ctx)
{
    if (ctx->backBuffer)
        IDirect3DSurface9_Release(ctx->backBuffer);
    if (ctx->renderTexture)
        IDirect3DTexture9_Release(ctx->renderTexture);
    if (ctx->sharedRenderSurface)
        IDirect3DSurface9_Release(ctx->sharedRenderSurface);
    if (ctx->sharedRenderTexture)
        IDirect3DTexture9_Release(ctx->sharedRenderTexture);
    if (ctx->rectangleFVFVertexBuf)
        IDirect3DVertexBuffer9_Release(ctx->rectangleFVFVertexBuf);
    if (ctx->libvlc_d3d)
        IDirect3DDevice9_Release(ctx->libvlc_d3d);
    IDirect3DDevice9_Release(ctx->d3ddev);
    IDirect3D9_Release(ctx->d3d);
}

static bool SetupDevice_cb( void **opaque, const libvlc_video_setup_device_cfg_t *cfg, libvlc_video_setup_device_info_t *out )
{
    struct render_context *ctx = *opaque;
    out->u.d3d9.device = ctx->d3d;
    out->u.d3d9.adapter = D3DADAPTER_DEFAULT;
    return true;
}

static void CleanupDevice_cb( void *opaque )
{
    /* here we can release all things Direct3D9 for good  (if playing only one file) */
    struct render_context *ctx = opaque;
    if (ctx->libvlc_d3d)
    {
        IDirect3DDevice9_Release(ctx->libvlc_d3d);
        ctx->libvlc_d3d = NULL;
    }
}

static void SetReport_cb( void *opaque,
    libvlc_video_output_resize_cb report_size_change,
    libvlc_video_output_mouse_move_cb report_mouse_move,
    libvlc_video_output_mouse_press_cb report_mouse_press,
    libvlc_video_output_mouse_release_cb report_mouse_release,
    void *report_opaque )
{
    struct render_context *ctx = opaque;
    EnterCriticalSection(&ctx->sizeLock);
    ctx->ReportSize = report_size_change;
    ctx->ReportOpaque = report_opaque;

    if (ctx->ReportSize != NULL)
    {
        /* report our initial size */
        ctx->ReportSize(ctx->ReportOpaque, ctx->width, ctx->height);
    }
    LeaveCriticalSection(&ctx->sizeLock);
}

static bool UpdateOutput_cb( void *opaque, const libvlc_video_render_cfg_t *cfg, libvlc_video_output_cfg_t *out )
{
    struct render_context *ctx = opaque;
    return Resize(ctx, cfg->width, cfg->height, (IDirect3DDevice9*)cfg->device, out);
}

static void Swap_cb( void* opaque )
{
    struct render_context *ctx = opaque;
    Swap( ctx );
}

/**
 * Callback called just before VLC starts/finishes drawing the video.
 *
 * Set the surface VLC will render to (could be the backbuffer if nothing else
 * needs to be displayed). And then call BeginScene().
 *
 * This is called outside of the UI thread (in the VLC rendering thread).
 */

static bool StartRendering_cb( void *opaque, bool enter )
{
    struct render_context *ctx = opaque;
    if ( enter )
    {
        /* we already set the RenderTarget on the IDirect3DDevice9 */
        return true;
    }

    /* VLC has finished preparing drawning on our surface, we need do the drawing now
       so the surface is finished rendering when Swap() is called to do our own
       rendering */

    IDirect3DDevice9_Present(ctx->libvlc_d3d, NULL, NULL, NULL, NULL);
    return true;
}

static const char *AspectRatio = NULL;

static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if( message == WM_CREATE )
    {
        /* Store p_mp for future use */
        CREATESTRUCT *c = (CREATESTRUCT *)lParam;
        SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)c->lpCreateParams );
        return 0;
    }

    LONG_PTR p_user_data = GetWindowLongPtr( hWnd, GWLP_USERDATA );
    if( p_user_data == 0 )
        return DefWindowProc(hWnd, message, wParam, lParam);
    struct render_context *ctx = (struct render_context *)p_user_data;

    switch(message)
    {
        case WM_SIZE:
        {
            /* tell libvlc that our size has changed */
            ctx->width  = (BORDER_RIGHT - BORDER_LEFT) * LOWORD(lParam) / SCREEN_WIDTH; /* remove the orange part ! */
            ctx->height = (BORDER_BOTTOM - BORDER_TOP) * HIWORD(lParam) / SCREEN_HEIGHT;
            EnterCriticalSection(&ctx->sizeLock);
            if (ctx->ReportSize != NULL)
                ctx->ReportSize(ctx->ReportOpaque, ctx->width, ctx->height);
            LeaveCriticalSection(&ctx->sizeLock);
        }
        break;

        case WM_DESTROY:
            {
                PostQuitMessage(0);
                return 0;
            }
            break;

        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
            {
                int key = tolower( MapVirtualKey( (UINT)wParam, 2 ) );
                if (key == 'a')
                {
                    if (AspectRatio == NULL)
                        AspectRatio = "16:10";
                    else if (strcmp(AspectRatio,"16:10")==0)
                        AspectRatio = "16:9";
                    else if (strcmp(AspectRatio,"16:9")==0)
                        AspectRatio = "4:3";
                    else if (strcmp(AspectRatio,"4:3")==0)
                        AspectRatio = "185:100";
                    else if (strcmp(AspectRatio,"185:100")==0)
                        AspectRatio = "221:100";
                    else if (strcmp(AspectRatio,"221:100")==0)
                        AspectRatio = "235:100";
                    else if (strcmp(AspectRatio,"235:100")==0)
                        AspectRatio = "239:100";
                    else if (strcmp(AspectRatio,"239:100")==0)
                        AspectRatio = "5:3";
                    else if (strcmp(AspectRatio,"5:3")==0)
                        AspectRatio = "5:4";
                    else if (strcmp(AspectRatio,"5:4")==0)
                        AspectRatio = "1:1";
                    else if (strcmp(AspectRatio,"1:1")==0)
                        AspectRatio = "fill";
                    else if (strcmp(AspectRatio,"fill")==0)
                        AspectRatio = NULL;
                    libvlc_video_set_aspect_ratio( ctx->p_mp, AspectRatio );
                }
                break;
            }
        default: break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;
    struct render_context Context = { 0 };
    char *file_path;
    libvlc_instance_t *p_libvlc;
    libvlc_media_t *p_media;
    (void)hPrevInstance;

    /* remove "" around the given path */
    if (lpCmdLine[0] == '"')
    {
        file_path = _strdup( lpCmdLine+1 );
        if (file_path[strlen(file_path)-1] == '"')
            file_path[strlen(file_path)-1] = '\0';
    }
    else
        file_path = _strdup( lpCmdLine );

    p_libvlc = libvlc_new( 0, NULL );
    p_media = libvlc_media_new_path( file_path );
    free( file_path );
    Context.p_mp = libvlc_media_player_new_from_media( p_libvlc, p_media, NULL, NULL );

    InitializeCriticalSection(&Context.sizeLock);

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = TEXT("WindowClass");

    RegisterClassEx(&wc);

    RECT wr = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

    hWnd = CreateWindowEx(0,
                          TEXT("WindowClass"),
                          TEXT("libvlc Demo app"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          wr.right - wr.left,
                          wr.bottom - wr.top,
                          NULL,
                          NULL,
                          hInstance,
                          &Context);

    ShowWindow(hWnd, nCmdShow);

    init_direct3d(&Context, hWnd);

    // DON'T use with callbacks libvlc_media_player_set_hwnd(p_mp, hWnd);

    /* Tell VLC to render into our D3D9 environment */
    libvlc_video_set_output_callbacks( Context.p_mp, libvlc_video_engine_d3d9,
                                       SetupDevice_cb, CleanupDevice_cb, SetReport_cb,
                                       UpdateOutput_cb, Swap_cb, StartRendering_cb,
                                       NULL, NULL, NULL,
                                       &Context );

    libvlc_media_player_play( Context.p_mp );

    MSG msg;

    while(TRUE)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
            break;
    }

    libvlc_media_player_stop_async( Context.p_mp );

    libvlc_media_player_release( Context.p_mp );
    libvlc_media_release( p_media );
    libvlc_release( p_libvlc );

    DeleteCriticalSection(&Context.sizeLock);
    release_direct3d(&Context);

    return (int)msg.wParam;
}

Messung
CHZG
859710094

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.