C++网络摄像头数据的获取与显示

最近因为项目的原因,需要和网络摄像头进行沟通,以谋取摄像头视频帧(因鱼眼摄像头有畸变,采用将每帧进行畸变处理—利用opencv提供的方法),尝试了很多方法,讲方法所示方法列出(本人技术渣渣,如有错误,请指教)

  • 采用VLC第三方库进行视频的获取
  • 采用opencv中rtsp协议
  • 采用opencv中http协议
    方法比较:
方法问题
VLC通常会出现延迟性问题
rtsp坏包
http开始时有延迟,等待3s后恢复正常

vlc demo 示例及部分理解:
介绍:VLC Media Player是一款优秀的播放器,但是由于它的源代码编译的难度比较大,一直没有深入研究过它的开发方面的技术。此前触到了一些VLC开发方面的东西,因此总结了一下libVLC的开发示例程序。获取vlc很简单,只需网上下载即可(此处自动忽略自行编译方法,因为windows下编译过于麻烦)
开发vlc文件位置
: 动态链接库*.dll:安装目录下的libvlc.dll,libvlccore.dll以及plugins目录下的所有文件。
PS:VLC支持非常多的plugin。因此plugins目录的体积确实是非常大的。
: 静态链接库*.lib:安装目录/sdk/lib
: 头文件*.h:安装目录/sdk/include
具体流程如图(此处参考libvlc视频播放器流程图)
视频播放器路程图
其中流程图中主要包括三个结构体,这些结构体实例用于创建相关的播放:
libVLC实例:libvlc_instance_t
播放媒体:libvlc_media_t
媒体播放器:libclv_media_player_t
以上的三个结构体通过以下函数进行创建和设置内容:

结构体函数 :

结构体创建释放
libvlc_instance_tlibvlc_new()libvlc_release
libvlc_media_tlibvlc_new_from_media()libvlc_media_release()
libclv_media_player_tlibvlc_media_player_new_from_medialibvlc_media_player_release()

注:1.函数控制媒体的播放和暂停(使用libvlc_media_player_t作为参数)
如:libvlc_media_player_X(),其中X={play,pause,stop}
2.创建libvlc_media_t方法:

方法用途示例
libvlc_media_new_path()打开文件(就是普通的文件路径(绝对路径例如D:\xxx.flv,或者相对路径例如xxx.flv))libvlc_media_new_path(“F:\movie\demo.flv”)
libvlc_media_new_location打开协议(广义协议,也可打开文件)libvlc_media_new_location(inst,”rtsp://admin:admin@192.168.1.115:554”);\n文件: libvlc_media_new_location(inst, “file:///F:\movie\demo.flv”);

此外,VLC还支持很多“神奇”的协议,比如输入“screen://”协议就可以进行屏幕录制,代码如下。
libvlc_media_new_location (inst, “screen://”);
示例代码:

#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <vlc/vlc.h>

#pragma comment(lib, "libvlc.lib")
#pragma comment(lib, "libvlccore.lib")

int main(int argc,char* argv[])
{
    libvlc_instance_t*inst;
    libvlc_media_t *m;
    libvlc_media_player_t *mp;

    libvlc_time_t length;
    int width;
    int height;
    int wait_time =5000;

    /* Load the VLC engine*/
    inst = libvlc_new(0,NULL);

    //Create a new item;
    //Method 1:
    m = libvlc_media_new_location(inst,"rtsp://admin:admin@192.168.1.115:554"); //用于打开协议;
     libvlc_media_add_option(m, ":network-caching=250");
    //Screen Capture;
    //m = libvlc_media_new_location(inst,"screen://");
    //Method 2: 
    //m = libvlc_media_new_path(inst,"c:\\1.avi");//用于打开文件;
    //m = libvlc_media_new_location(inst,"file:///c:\\1.avi");//广义协议;

     /* Create a media player playing environement */ 
    mp = libvlc_media_player_new_from_media(m);

    length = libvlc_media_player_get_length(mp);
    // play the media_player;
    libvlc_media_player_play(mp);
    //Let it play;
    _sleep(length-wait_time);

    //Stop playing;
    libvlc_media_player_stop(mp);

    //Free the media_player;
    libvlc_media_player_release(mp);

    libvlc_media_release(m);
    libvlc_release(inst);
    return 0;
}

说了这么多,可以简单实现播放视频数据了,现在进入我所需要的,获取视频中的每一帧;
为了从Rtsp地址获取实时帧数据, VLC作为Rtsp的客户端,拉网络视频流。然后进行实时解码(内部进行),自己获得码流(RGBA数据,32位RGB),显示
基本流程:
1.libvlc_new()
2.libvlc_media_new_location()
3.libvlc_media_player_new_from_meida() //构建mediaplayer;
4.libvlc_video_set_callbacks()
5.libvlc_media_player_play() //注:重要,获取视频帧时,需要将mp进行运行才行;
loop
6.release:
libvlc_media_player_release
libvlc_release
说明:
1、libvlc_video_set_callbacks //为了获得实时流,就需要进行回调libvlc_video_set_callbacks
需要设置三个回调,我们需要获得buffer的大小,视频的width和height
buffer = width*height*4;
在lock函数中需要锁住,在unlock中解锁。实际上的是display

相关函数 LIBVLC_API
void libvlc_video_set_callbacks( libvlc_media_player_t *mp,
libvlc_video_lock_cb lock,
libvlc_video_unlock_cb unlock,
libvlc_video_display_cb display,
void *opaque );

这个函数的作用如下:
1.mp是media player的一个实例。
2.lock,每当有视频进行新的一帧的解码时,会调用lock来锁住内存。

3.unlock,在解码完至显示之间,可对每一帧数据进行操作。

4.display,对数据进行显示。

5.opaque,唯一的一个传递参数的指针。所以,一般都是指向一个结构体,而结构体包括了很多其它需要的参数
libvlc_video_set_callbacks()函数 ,它的参数有三个回调函数,格式类似:

 void *lock(void *opaque,  void **plane);     //opaque, 唯一的一个传递参数的指针,传递参数结构体
                                                                 //planes  指向图像阵列
 //此函数还会返回图像buffer的指针,供unlock和display使用,即为picture指针。

 void  unlock(void *opaque, void *picture, void *const *planes);     //picture即为lock返回的指针
 void  display(void *opaque, void *picture);                                   //该函数用opaque和picture进行显示

另外,还要搭配libvlc_video_set_format或者libvlc_video_set_format_callbacks使用

 void libvlc_video_set_format( libvlc_media_player_t *mp, const char *chroma,
                           unsigned width, unsigned height,
                           unsigned pitch );
 注:chroma是形如“RV32”、“YUYV”的字符串。pitch一般是height的4倍

  void libvlc_video_set_format_callbacks( libvlc_media_player_t *mp,
                                libvlc_video_format_cb setup,
                                libvlc_video_cleanup_cb cleanup );
 setup:

      typedef unsigned (*libvlc_video_format_cb)(void **opaque, char *chroma,
                                        unsigned *width, unsigned *height,
                                        unsigned *pitches,
                                        unsigned *lines);
     注: **opaque指向opaque的指针的指针,用于传入libvlc_video_set_callbacks的参数。chroma如上,用形如strcpy(chroma,”RV32”)即可。此处width和height均可重新定义。pitches一般height的4倍,lines一般等于width。

 cleanup:

      typedef void (*libvlc_video_cleanup_cb)(void *opaque);
     注:用于释放已分配的内存。可以是NULL。

该扯的扯的差不多了,现在说一下他的延迟问题,本渣渣查了很多资料,不知道延迟问题如何解决,始终存在1s左右的延迟,查资料解决如下:
libvlc_media_add_option(m_vlcMedia,":network-caching=300");//网络延迟时间也可以根据需要修改,这个值越小,实时性越好,当然太小了播放会很卡,或者设置的值失效;一般建议在100-300之间,如果网络环境较好,300ms以内效果很好,实时性较好;
最终效果保证在1s内,但是仍有延迟。
文章太长了,下篇介绍opencv访问网络摄像头

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值