Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hi, I have had similar problems (and solved them) as I'll explain below. The approach to solve it, is nearly identical. My O.S is Windows 7 64 bits and I was using VC++2013.

  • When streaming H264 video from IP cameras using RTSP with OpenCV , the program crashes after some minutes without a clear reason (tested it with OpenCV 3 and OpenCV 2.4.9...).

  • Tried to use FFMPEG, but compiling FFMPEG was quite hard on Windows. I could not compile it correctly following the instructions I've found.

The solution: I tried libVLC and got it working for 32bits EXEs and 64 bits EXEs using:

  • DLLs and plugins from VLC player 2.2.1 (if you want to generate a 64 bit EXE use the DLLs from VLC 2.2.1 64 bits, if you want to generate a 32 bit EXE use the DLLs from VLC 2.2.1 32 bits).

  • .lib files and .h files for libVLC 32bits and 64 bits can be found here: https://github.com/RSATom/libvlc-sdk

  • I created a simple Console project following this tutorial (https://wiki.videolan.org/LibVLC_SampleCode_SDL/#SDL_2.0) and added some modifications. (See the full code below). Notice the code does not use OpenCV at all, but once you got the frames, you can add OpenCV to run any process on them.

I would love to see a better RTSP support in OpenCV because everything would be easier but this is the only way I've found to solve the crashes.

include <iostream>

include <stdio.h>

include <stdint.h>

include <math.h>

include <stdlib.h>

include <assert.h>

include "SDL.h"

include "SDL_mutex.h"

include "vlc/vlc.h"

define WIDTH 800

define HEIGHT 600

define VIDEOWIDTH 320

define VIDEOHEIGHT 240

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

// 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;

// display the video in a random location
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);

// display the video in the top left corner
//rect.x = 0;
//rect.y = 0;

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[]) { // libSDL and libVLC sample code. // License: [http://en.wikipedia.org/wiki/WTFPL WTFPL]

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]);                                                           // for video in local files
m = libvlc_media_new_location(libvlc, "rtsp://192.168.2.120:554/snl/live/1/1/Ux/sido=-Ux/sido=");       // for streaming video in URLs (or local files using file:// ....)

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;

}

Blockquote

Hi, I have had similar problems (and solved them) as I'll explain below. The approach to solve it, is nearly identical. My O.S is Windows 7 64 bits and I was using VC++2013.

  • When streaming H264 video from IP cameras using RTSP with OpenCV , the program crashes after some minutes without a clear reason (tested it with OpenCV 3 and OpenCV 2.4.9...).

  • Tried to use FFMPEG, but compiling FFMPEG was quite hard on Windows. I could not compile it correctly following the instructions I've found.

The solution: I tried libVLC and got it working for 32bits EXEs and 64 bits EXEs using:

  • DLLs and plugins from VLC player 2.2.1 (if you want to generate a 64 bit EXE use the DLLs from VLC 2.2.1 64 bits, if you want to generate a 32 bit EXE use the DLLs from VLC 2.2.1 32 bits).

  • .lib files and .h files for libVLC 32bits and 64 bits can be found here: https://github.com/RSATom/libvlc-sdk

  • I created a simple Console project following this tutorial (https://wiki.videolan.org/LibVLC_SampleCode_SDL/#SDL_2.0) and added some modifications. (See the full code below). Notice the code does not use OpenCV at all, but once you got the frames, you can add OpenCV to run any process on them.

I would love to see a better RTSP support in OpenCV because everything would be easier but this is the only way I've found to solve the crashes.crashes. Please, check the code because it is a fast try...it could contain bugs.

include <iostream>

include <stdio.h>

include <stdint.h>

include <math.h>

include <stdlib.h>

include <assert.h>

include "SDL.h"

include "SDL_mutex.h"

include "vlc/vlc.h"

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

#include "SDL.h"
#include "SDL_mutex.h"
#include "vlc/vlc.h"

#define WIDTH 800

define 800 #define HEIGHT 600

define 600 #define VIDEOWIDTH 320

define 320 #define VIDEOHEIGHT 240

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

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

**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;
 // display the video in a random location
 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);
 // display the video in the top left corner
 //rect.x = 0;
 //rect.y = 0;
 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[]) { // libSDL and libVLC sample code. // License: [http://en.wikipedia.org/wiki/WTFPL WTFPL]

WTFPL]
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  // UNCOMMENT THIS IF YOU INTEND TO PLAY A LOCAL VIDEO
//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]);  // for video in local files
m = libvlc_media_new_location(libvlc, "rtsp://192.168.2.120:554/snl/live/1/1/Ux/sido=-Ux/sido=");  //m = libvlc_media_new_path(libvlc, argv[1]);
 // for streaming video in URLs (or local files using file:// ....)
  m = libvlc_media_new_location(libvlc, "rtsp://192.168.2.120:554/snl/live/1/1/Ux/sido=-Ux/sido=");
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;
}

}