1. 程式人生 > >Read rtsp using libvlc&opencv

Read rtsp using libvlc&opencv

1. Problem

I need to read video frame from a rtsp device, and convert it to cv::Mat.

2. Solution

libvlc is a useful tool.

  1. sudo apt-get install libvlc-dev
  2. Create VLCReader class.

2.1 VLCReader.h

#ifndef VLCREADER_H
#define VLCREADER_H

#include <vlc/vlc.h>
#include <opencv2/opencv.hpp>
class VLCReader { public: VLCReader(char* url=0); ~VLCReader(); void start(int wantW = 640, int wantH=480); void pause(bool paused); cv::Mat frame(){ return img;} int w, h; private: char* rtspAddress = "rtsp://192.168.9.7/bs1"; libvlc_instance_t *inst; libvlc_media_player_t *mp; unsigned char
*pixel; cv::Mat img; static void *cb_lock(void *opaque, void **plane); static void cb_unlock(void *opaque, void *picture, void * const *plane); static void cb_display(void *opaque, void *picture); unsigned char * updataSize(); }; #endif // VLCREADER_H

2.2 VLCReader.cpp

#include "vlcreader.h"
#include <cstdlib> #include <iostream> VLCReader::VLCReader(char*url) : inst(0),mp(0), pixel(0), w(0), h(0), rtspAddress(url) { const char * const vlc_args[] = { "-I", "dummy", // Don't use any interface "--ignore-config", // Don't use VLC's config "--no-audio", // skip any audio track "--verbose=1", // change verbosity for debugging purpose }; inst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); mp = libvlc_media_player_new(inst); libvlc_video_set_callbacks(mp, &cb_lock, &cb_unlock, &cb_display, this); } VLCReader::~VLCReader() { libvlc_media_player_stop(mp); libvlc_media_player_release(mp); libvlc_release(inst); } void VLCReader::start(int wantW, int wantH) { libvlc_media_player_pause(mp); libvlc_media_t *media = libvlc_media_new_location(inst, rtspAddress); libvlc_media_player_set_media(mp, media); libvlc_media_release(media); libvlc_video_set_format(mp, "RV24", wantW, wantH, wantW*3); libvlc_media_player_play(mp); } void VLCReader::pause(bool paused) { if(mp){ libvlc_media_player_set_pause(mp, paused); } } unsigned char * VLCReader::updataSize() { int w = libvlc_video_get_width(mp); int h = libvlc_video_get_height(mp); if (!w || !h) return 0; if (pixel && (this->w != w || this->h != h)){ delete[] pixel; pixel = 0; } if (!pixel){ pixel = new unsigned char[w*h*3]; this->w = w; this->h = h; } return pixel; } void* VLCReader::cb_lock(void *opaque, void **plane) { VLCReader *p = (VLCReader*) opaque; *plane = p->updataSize(); return *plane; } void VLCReader::cb_unlock(void *opaque, void *picture, void * const *plane) { VLCReader *p = (VLCReader*) opaque; unsigned char *pix = (unsigned char*)picture; if (pix){ p->img = cv::Mat(p->h, p->w, CV_8UC3, pix); } } void VLCReader::cb_display(void *opaque, void *picture) { }

2.3 Test

#include <opencv2/opencv.hpp>
#include "vlcreader.h"
using namespace cv;

int main()
{
    VLCReader r("rtsp://192.168.9.7/bs1");
    int rtsp_w = 720, rtsp_h = 576;
    r.start(rtsp_w, rtsp_h);

    while(1){
        Mat frame = r.frame();
        if(!frame.empty()){
            imshow("test", frame);
            int ch = waitKey(20) & 0xFF;
            if (ch == 113)
                break;
        }
    }
    return 0;
}

3. ref