Read rtsp using libvlc&opencv
阿新 • • 發佈:2019-02-19
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.
- sudo apt-get install libvlc-dev
- 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;
}