用 VLC 打开 rtsp 流,并用 OPencv 处理播放;
原始出处:https://forum.videolan.org/viewtopic.php?t=87031,
自己测试代码如下 vlc2.2.1, opencv2.4.11
#define _SKY_VIDEO_WIDTH 800
#define _SKY_VIDEO_HEIGHT 600
#define _WINDOWN_SHOW "YS_SHOW"
typedef struct _CTX_
{
cv::Mat *image;
HANDLE mutex;
uchar* pixels;
}CTX, *PCTX;
//Vlc
libvlc_instance_t* pVlcInstance;
libvlc_media_player_t* pMediaPlayer;
libvlc_media_t* pMedia;
libvlc_event_manager_t *pEventManager;
//结构体
PCTX pContext;
static void *lock(void* data, void** p_pixels);
static void display(void *data, void *id);
static void unlock(void *data, void* id, void* const* p_pixels);
static void handleEvent(const libvlc_event_t* pEvt, void* pUserData);
//构造函数
const char* _vlc_args[] = {
"-I",
"dumy",
"--ignore-config",
"--plugin-path=./plugins",
"--no-video-title-show",
"--rtsp-tcp"
};
char* _playurl = "rtmp://live.hkstv.hk.lxdns.com/live/hks";
//char* _playurl = "rtsp://=====;
//char* _playurl = "D:\\Video\\CitySky.mp4";
pVlcInstance = libvlc_new(sizeof(_vlc_args) / sizeof(_vlc_args[0]), _vlc_args);
pContext = (PCTX)malloc(sizeof(CTX));
pContext->mutex = ::CreateMutex(NULL, FALSE, NULL);
pContext->image = new cv::Mat(_SKY_VIDEO_HEIGHT, _SKY_VIDEO_WIDTH, CV_8UC3);
pContext->pixels = (unsigned char*)pContext->image->data;
//cv::imshow(_WINDOWN_SHOW, *pContext->image);
cv::namedWindow(_WINDOWN_SHOW);
//pMedia = libvlc_media_new_path(pVlcInstance, _playurl);//用这个可以播放本地的文件
pMedia = libvlc_media_new_location(pVlcInstance, _playurl);// 播放rtsp或者rtmp的时候
用这个,
pMediaPlayer = libvlc_media_player_new_from_media(pMedia);
libvlc_media_release(pMedia);
libvlc_video_set_callbacks(pMediaPlayer, lock, unlock, display, pContext);
libvlc_video_set_format(pMediaPlayer, "RV24", _SKY_VIDEO_WIDTH,
_SKY_VIDEO_HEIGHT, _SKY_VIDEO_WIDTH * 24 / 8);
libvlc_media_player_play(pMediaPlayer);
void* vlcopencv::lock(void* data, void** p_pixels)
{
}
PCTX _ctx = (PCTX)data;
WaitForSingleObject(_ctx->mutex, INFINITE);
// pixel will be stored on image pixel space
*p_pixels = _ctx->pixels;
return NULL;
void vlcopencv::display(void *data, void *id)
{
}
(void)data;
assert(id == NULL);
void vlcopencv::unlock(void *data, void* id, void* const* p_pixels)
{
// get back data structure
PCTX _ctx = (PCTX)data;
/* VLC just rendered the video, but we can also render stuff */
// show rendered image
std::string _text = "VLC-OPENCV";
srand(time(NULL));
cv::putText(*_ctx->image, _text, cv::Point(15, 25), cv::FONT_HERSHEY_SIMPLEX, 1.0,
cv::Scalar(rand() % 255, rand() % 255, rand() % 255));
cv::imshow(_WINDOWN_SHOW, *_ctx->image);
ReleaseMutex(_ctx->mutex);
}
//如果中间要打开新的流串,把构造函数里的代码封装成一个函数,重新走一遍,否者程序会“停止
运行”,注意内存的释放。
//用的是 rmtp 串测试的,最新的 vlc 支持 rtmp,截图如下: