0

I am trying the simple libvlc demo with libsdl2 from LibVLC Sample Code SDL but I am having issues when running the compiled binary. I get a "Couldn't find matching render driver" error from SDL_GetError() after SDL_CreateRenderer(). here is the source:

// libSDL and libVLC sample code.
// License: [http://en.wikipedia.org/wiki/WTFPL WTFPL]

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

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

#include <vlc/vlc.h>

#define WIDTH 640
#define HEIGHT 480

#define VIDEOWIDTH 320
#define VIDEOHEIGHT 240

typedef struct context {
    SDL_Renderer *renderer;
    SDL_Texture *texture;
    SDL_mutex *mutex;
    int n;
} context;

// VLC prepares to render a video frame.
static void *lock(void *data, void **p_pixels) {

    struct context *c = (context *)data;

    int pitch;
    SDL_LockMutex(c->mutex);
    SDL_LockTexture(c->texture, NULL, p_pixels, &pitch);

    return NULL; // Picture identifier, not needed here.
}

// VLC just rendered a video frame.
static void unlock(void *data, void *id, void *const *p_pixels) {

    struct context *c = (context *)data;

    uint16_t *pixels = (uint16_t *)*p_pixels;

    // We can also render stuff.
    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 {
                // RV16 = 5+6+5 pixels per color, BGR.
                pixels[y * VIDEOWIDTH + x] = 0x02ff;
            }
        }
    }

    SDL_UnlockTexture(c->texture);
    SDL_UnlockMutex(c->mutex);
}

// VLC wants to display a video frame.
static void display(void *data, void *id) {

    struct context *c = (context *)data;

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

    SDL_SetRenderDrawColor(c->renderer, 0, 80, 0, 255);
    SDL_RenderClear(c->renderer);
    SDL_RenderCopy(c->renderer, c->texture, NULL, &rect);
    SDL_RenderPresent(c->renderer);
}

static void quit(int c) {
    SDL_Quit();
    exit(c);
}

int main(int argc, char *argv[]) {

    libvlc_instance_t *libvlc;
    libvlc_media_t *m;
    libvlc_media_player_t *mp;
    char const *vlc_argv[] = {

        "--no-audio", // Don't play audio.
        "--no-xlib", // Don't use Xlib.

        // Apply a video filter.
        //"--video-filter", "sepia",
        //"--sepia-intensity=200"
    };
    int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);

    SDL_Event event;
    int done = 0, action = 0, pause = 0, n = 0;

    struct context context;

    if(argc < 2) {
        printf("Usage: %s <filename>\n", argv[0]);
        return EXIT_FAILURE;
    }

    // Initialise libSDL.
    if(SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("Could not initialize SDL: %s.\n", SDL_GetError());
        return EXIT_FAILURE;
    }

    // Create SDL graphics objects.
    SDL_Window * window = SDL_CreateWindow(
            "Fartplayer",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            WIDTH, HEIGHT,
            SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
    if (!window) {
        fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
        quit(3);
    }

    context.renderer = SDL_CreateRenderer(window, -1, 0);
    if (!context.renderer) {
        fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
        quit(4);
    }

    context.texture = SDL_CreateTexture(
            context.renderer,
            SDL_PIXELFORMAT_BGR565, SDL_TEXTUREACCESS_STREAMING,
            VIDEOWIDTH, VIDEOHEIGHT);
    if (!context.texture) {
        fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
        quit(5);
    }

    context.mutex = SDL_CreateMutex();

    // If you don't have this variable set you must have plugins directory
    // with the executable or libvlc_new() will not work!
    printf("VLC_PLUGIN_PATH=%s\n", getenv("VLC_PLUGIN_PATH"));

    // Initialise libVLC.
    libvlc = libvlc_new(vlc_argc, vlc_argv);
    if(NULL == libvlc) {
        printf("LibVLC initialization failure.\n");
        return EXIT_FAILURE;
    }

    m = libvlc_media_new_path(libvlc, argv[1]);
    mp = libvlc_media_player_new_from_media(m);
    libvlc_media_release(m);

    libvlc_video_set_callbacks(mp, lock, unlock, display, &context);
    libvlc_video_set_format(mp, "RV16", VIDEOWIDTH, VIDEOHEIGHT, VIDEOWIDTH*2);
    libvlc_media_player_play(mp);

    // Main loop.
    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:
            case SDLK_q:
                done = 1;
                break;
            case ' ':
                printf("Pause toggle.\n");
                pause = !pause;
                break;
        }

        if(!pause) { context.n++; }

        SDL_Delay(1000/10);
    }

    // Stop stream and clean up libVLC.
    libvlc_media_player_stop(mp);
    libvlc_media_player_release(mp);
    libvlc_release(libvlc);

    // Close window and clean up libSDL.
    SDL_DestroyMutex(context.mutex);
    SDL_DestroyRenderer(context.renderer);

    quit(0);

    return 0;
}

As you can see (if you checked the link) I've only done a few modification to the code:

  • replace "SDL.h" with
  • replace struct context{...}; with typedef struct context{...}context;

I don't know what the issue is but I am pretty sure it is SDL related because even a simple SDL example where I'm just clearing the screen doesn't work properly. As shown by the picture below:

this picture show the SDL window "Hello World" not clearing itself.

As you can see, instead of clearing the window the renderer of the "Hello World" SDL Window does nothing. And all we see it everything that is behind the SDL Window. I moved the SDL "Hello World" window before taking the screenshot. That's why things look like they are out of place.

Here is the code for the simple SDL Hello World app:

#include <SDL2/SDL.h>

int main(int argc, char *argv[]) {
    SDL_Window *win = NULL;
    SDL_Renderer *renderer = NULL;
    int posX = 100, posY = 100, width = 640, height = 480;

    SDL_Init(SDL_INIT_VIDEO);

    win = SDL_CreateWindow("Hello World", posX, posY, width, height, 0);

    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);

    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    while (1) {
        SDL_Event e;
        if (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                break;
            }
        }

        SDL_RenderClear(renderer);
        SDL_RenderPresent(renderer);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);

    SDL_Quit();

    return 0;
}

Please note that the SDL Hello World app doesn't generate a "Couldn't find matching render driver" error. Although I would appreciate finding a solution for both the issue (my main concern is the libvlc one); solving the Hello World app might not necessarily solve the libvlc app.

Also note that I am running everything on the Kano OS (some kind of fork of the Raspbian OS from Kano ).

9
  • One thing I could imagine is that as you execute the Clear and Present Methods in while loop. They got executed in a very fast sequence. And perhaps the Clear method stops the present method from present the changes because there is new work to be shown. And that again and again. I would place both lines SDL_DestroyRenderer(renderer); SDL_DestroyWindow(win); above the wile(1) loop. That may help. Nov 9 '19 at 17:27
  • By the way: Do you really want to call the Window "Fartplayer". ;-) Hhhm. Nov 9 '19 at 17:37
  • @PeterPaulKiefer I don't know if you've used SDL before (I can guess though). But I can give you an analogy to what you're asking me: It would be like getting a surgery to remove your lungs and then hope you can breath. I've used SDL in the past on MS Windows but never tried that (I knew it would never work) but I tried today. The App crashed! You can't clear, present, render a renderer without a renderer. I also tried slowing down the while loop the right way (with SDL_Delay()). I did it even though It's not necessary on Windows thinking that maybe Pi3 is not powerful enough. Didn't work.
    – Paiku Han
    Nov 9 '19 at 18:59
  • @PeterPaulKiefer "Fartplayer" is what was written on the original source. I just copied and pasted the code then changed just what needed to be changed. :D.
    – Paiku Han
    Nov 9 '19 at 19:01
  • Sorry, I did a terrible mistake. I copied the wrong function names. As I wrote in the first line, I meant the clear ant present method to be moved above the while loop. And yes, you're right, I've not used SDL for a long time. But I am an experienced developer (>25 years) and saw my mistake at once after you mentioned. Nov 10 '19 at 12:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.