Difference between revisions of "LibVLC SampleCode SDL"

From VideoLAN Wiki
Jump to navigation Jump to search
(cool libSDL/libVLC example)
 
(convert to media and media player)
Line 71: Line 71:
 
     libvlc_exception_t ex;
 
     libvlc_exception_t ex;
 
     libvlc_instance_t *libvlc;
 
     libvlc_instance_t *libvlc;
     libvlc_media_descriptor_t *md;
+
     libvlc_media_t *m;
     libvlc_media_instance_t *mi;
+
     libvlc_media_player_t *mp;
 
     char const *vlc_argv[] =
 
     char const *vlc_argv[] =
 
     {
 
     {
Line 140: Line 140:
 
     libvlc = libvlc_new(vlc_argc, vlc_argv, &ex);
 
     libvlc = libvlc_new(vlc_argc, vlc_argv, &ex);
 
     catch(&ex);
 
     catch(&ex);
     md = libvlc_media_descriptor_new(libvlc, argv[1], &ex);
+
     m = libvlc_media_new(libvlc, argv[1], &ex);
 
     catch(&ex);
 
     catch(&ex);
     mi = libvlc_media_instance_new_from_media_descriptor(md, &ex);
+
     mp = libvlc_media_player_new_from_media(m, &ex);
 
     catch(&ex);
 
     catch(&ex);
     libvlc_media_descriptor_release(md);
+
     libvlc_media_release(m);
  
     libvlc_media_instance_play(mi, &ex);
+
     libvlc_media_player_play(mp, &ex);
 
     catch(&ex);
 
     catch(&ex);
  
Line 208: Line 208:
 
     * Stop stream and clean up libVLC
 
     * Stop stream and clean up libVLC
 
     */
 
     */
     libvlc_media_instance_stop(mi, &ex);
+
     libvlc_media_player_stop(mp, &ex);
 
     catch(&ex);
 
     catch(&ex);
  
     libvlc_media_instance_release(mi);
+
     libvlc_media_player_release(mp);
 
     libvlc_release(libvlc);
 
     libvlc_release(libvlc);
  

Revision as of 01:16, 30 March 2008

This sample code will render a video into an SDL surface.

NOTE: this requires the "vmem" video output which was checked in on March 21st, 2008.

/* libSDL and libVLC sample code
 * Copyright © 2008 Sam Hocevar <sam@zoy.org>
 * license: [http://en.wikipedia.org/wiki/WTFPL WTFPL] */

#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>

#include <SDL.h>
#include <SDL_mutex.h>

#include <vlc/libvlc.h>

#define WIDTH 640
#define HEIGHT 480

#define VIDEOWIDTH 320
#define VIDEOHEIGHT 240

struct ctx
{
    SDL_Surface *surf;
    SDL_mutex *mutex;
};

static void catch (libvlc_exception_t *ex)
{
    if(libvlc_exception_raised(ex))
    {
        fprintf(stderr, "exception: %s\n", libvlc_exception_get_message(ex));
        exit(1);
    }

    libvlc_exception_clear(ex);
}

static void * lock(struct ctx *ctx)
{
    SDL_LockMutex(ctx->mutex);
    SDL_LockSurface(ctx->surf);
    return ctx->surf->pixels;
}

static void unlock(struct ctx *ctx)
{
    /* VLC just rendered the video, but we can also render stuff */
    uint16_t *pixels = (uint16_t *)ctx->surf->pixels;
    int x, y;

    for(y = 10; y < 40; y++)
        for(x = 10; x < 40; x++)
            if(x < 13 || y < 13 || x > 36 || y > 36)
                pixels[y * VIDEOWIDTH + x] = 0xffff;
            else
                pixels[y * VIDEOWIDTH + x] = 0x0;

    SDL_UnlockSurface(ctx->surf);
    SDL_UnlockMutex(ctx->mutex);
}

int main(int argc, char *argv[])
{
    char clock[64], cunlock[64], cdata[64];
    char width[32], height[32], pitch[32];
    libvlc_exception_t ex;
    libvlc_instance_t *libvlc;
    libvlc_media_t *m;
    libvlc_media_player_t *mp;
    char const *vlc_argv[] =
    {
        "-q",
        //"-vvvvv",
        "--plugin-path", VLC_TREE "/modules",
        "--noaudio",
        "--vout", "vmem",
        "--vmem-width", width,
        "--vmem-height", height,
        "--vmem-pitch", pitch,
        "--vmem-chroma", "RV16",
        "--vmem-lock", clock,
        "--vmem-unlock", cunlock,
        "--vmem-data", cdata,
    };
    int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);

    SDL_Surface *screen, *empty;
    SDL_Event event;
    SDL_Rect rect;
    int done = 0, action = 0, pause = 0, n = 0;

    struct ctx ctx;

    /*
     *  Initialise libSDL
     */
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) == -1)
    {
        printf("cannot initialize SDL\n");
        return EXIT_FAILURE;
    }

    empty = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT,
                                 32, 0, 0, 0, 0);
    ctx.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT,
                                    16, 0x001f, 0x07e0, 0xf800, 0);

    ctx.mutex = SDL_CreateMutex();

    int options = SDL_ANYFORMAT | SDL_HWSURFACE | SDL_DOUBLEBUF;

    screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options);
    if(!screen)
    {
        printf("cannot set video mode\n");
        return EXIT_FAILURE;
    }

    /*
     *  Initialise libVLC
     */
    sprintf(clock, "%lld", (long long int)(intptr_t)lock);
    sprintf(cunlock, "%lld", (long long int)(intptr_t)unlock);
    sprintf(cdata, "%lld", (long long int)(intptr_t)&ctx);
    sprintf(width, "%i", VIDEOWIDTH);
    sprintf(height, "%i", VIDEOHEIGHT);
    sprintf(pitch, "%i", VIDEOWIDTH * 2);

    if(argc < 2)
    {
        printf("too few arguments (MRL needed)\n");
        return EXIT_FAILURE;
    }
    libvlc_exception_init(&ex);
    libvlc = libvlc_new(vlc_argc, vlc_argv, &ex);
    catch(&ex);
    m = libvlc_media_new(libvlc, argv[1], &ex);
    catch(&ex);
    mp = libvlc_media_player_new_from_media(m, &ex);
    catch(&ex);
    libvlc_media_release(m);

    libvlc_media_player_play(mp, &ex);
    catch(&ex);

    /*
     *  Main loop
     */
    rect.w = 0;
    rect.h = 0;

    while(!done)
    { 
        action = 0;

        /* Keys: enter (fullscreen), space (pause), escape (quit) */
        while( SDL_PollEvent( &event ) ) 
        { 
            switch(event.type)
            {
            case SDL_QUIT:
                done = 1;
                break;
            case SDL_KEYDOWN:
                action = event.key.keysym.sym;
                break;
            }
        }

        switch(action)
        {
        case SDLK_ESCAPE:
            done = 1;
            break;
        case SDLK_RETURN:
            options ^= SDL_FULLSCREEN;
            screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options);
            break;
        case ' ':
            pause = !pause;
            break;
        }

        rect.x = (int)((1. + .5 * sin(0.03 * n)) * (WIDTH - VIDEOWIDTH) / 2);
        rect.y = (int)((1. + .5 * cos(0.03 * n)) * (HEIGHT - VIDEOHEIGHT) / 2);

        if(!pause)
            n++;

        /* Blitting the surface does not prevent it from being locked and
         * written to by another thread, so we use this additional mutex. */
        SDL_LockMutex(ctx.mutex);
        SDL_BlitSurface(ctx.surf, NULL, screen, &rect);
        SDL_UnlockMutex(ctx.mutex);

        SDL_Flip(screen);
        SDL_Delay(10);

        SDL_BlitSurface(empty, NULL, screen, &rect);
    }

    /*
     * Stop stream and clean up libVLC
     */
    libvlc_media_player_stop(mp, &ex);
    catch(&ex);

    libvlc_media_player_release(mp);
    libvlc_release(libvlc);

    /*
     * Close window and clean up libSDL
     */
    SDL_DestroyMutex(ctx.mutex);
    SDL_FreeSurface(ctx.surf);
    SDL_FreeSurface(empty);

    SDL_Quit();

    return 0;
}