如何在VLC中支持IPv6 RTSP流媒体播放

国产化系统-使用VLC测试IPV4与IPV6组播 8、注意,该步骤是关键,如果要测试IPV4,将地址设置为IPV4组播段得地址即可,比如:239.1.1.1,如果要测试IPV6,将地址设置为IPV6组播段得地址即可,比如:ff15::1;设置好后,点击下一个。13、点击播放后,组播客户端可以拉去到组播服务器的流(视频打开比较慢,耐心等待30秒左右,视频还有可能出现播放不了或者效果不好,但这都不是我们关注的,只要vlc下方有时间轴,基本说明有数据过来了)5、点击串流,如果此时看到的不是“串流”,可以点击下拉按钮,选择“串流”后,再点击。 阅读详情

前段时间遇到一个项目,要求在IPv6的网络环境中实现RTSP流媒体播放,支持点播和直播。然而,RTSP 1.0协议,RFC2326中并未定义如何支持IPv6,因此很多人认为在IPv6网络环境中无法实现RTSP 1.0的流媒体播放,而RTSP 2.0目前还处于草案状态,并未最终通过评审成为标准。

事实上,在IPv6网络环境中,只需要对RTSP 1.0略作修改就可以实现,一些厂商也已经这样做了,比如AXIS。

本文将要介绍的,是如何在开源软件VLC的基础上,修改它的RTSP协议栈使之能够支持IPv6,并能够在IPv6的网络环境中成功连接AXIS的网络摄像机实现视频播放的过程。

1  下载并编译VLC

在www.videolan.org下载VLC的最新版本源码,vlc-1.1.0-rc3.tar.bz2,然后按照网站wiki的说明进行编译。由于是要在win32平台编译,我倾向用MinGW编译环境。

http://wiki.videolan.org/Win32CompileMSYSNew这里给出了VLC编译的详细步骤,严格按照这里给出的步骤操作,除了中间有一次libtool脚本的一个错误,Google上很容易找到解决的方法,之后就没有遇到其他的问题,成功编译出VLC的执行码和所有的plugin。

网上经常有人抱怨下载的VLC源码无法成功编译,遇到各种各样的问题,绝大多数时候,是因为没有严格遵照wiki上的步骤来操作。

VLC编译成功之后,接下来,我们需要聚焦到liblive555_plugin.dll这个插件上来,因为是这个插件实现了VLC的RTSP客户端协议栈。我们除了要修改modules/demux/live555.cpp之外,还需要修改并重新编译live555的库文件。

2  下载并编译Live555

www.live555.com 下载live555的最新源码包,解压到/home/[user]/live 下,然后运行:

cd live

./genMakefiles mingw

make

编译成功后将生成的libgroupsock.a, libliveMedia.a,libBasicUsageEnvironment.a, libUsageEnvironment.a拷贝到 /win32/lib 路径下,覆盖原来的live555库文件,再把相关的头文件拷贝到 /win32/include 路径下,覆盖原来的live555 头文件。

接下来,需要重新编译VLC,确保这个版本的live555与vlc可以配合工作。

上面这些工作完成后,我们就有了一套可以用来进行IPv6改造的可用的基础代码。

3  Live555的修改要点

3.1  NetAddress.hh

NetAddress.hh中定义了网络地址的基础数据结构,可以看到设计者考虑到了未来向IPv6的扩展,但是做的还不够。设计者原本考虑的是在NetAddress类中放入一个struct sin_addr或者是一个struct sin6_addr,但这样的设计不能够满足IPv6时socket的各种操作,因此,我决定将整个struct sockaddr_in或struct sockaddr_in6都放在NetAddress的fData缓冲区中。

在NetAddress.hh的NetAddress类中增加一个public接口函数getFamily,用于确定这个NetAddress是IPv4地址还是IPv6地址:

int getFamily()

{

        struct sockaddr* addr = (structsockaddr*)fData;

        return addr->sa_family;

}

3.2  inet.c

inet.c中实现了IP地址从字符串形式与网络地址形式之间的相互转换。IPv4地址的字符串形式是ddd.ddd.ddd.ddd,其中d是一个十进制数,ddd的取值范围是0~255;IPv6地址的字符串形式是xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx,其中x是一个十六进制数,xxxx的取值范围是0~ffff,地址中如果存在连续多个字段为0,可以采用双冒号的形式进行压缩,比如fe80::1表示fe80:0:0:0:0:0:0:1。

our_inet_addr用于将一个字符串形式的IP地址转换为网络地址,要兼容IPv6地址就必须进行改写。

将our_inet_addr函数的实现修改为(其中inet_pton函数可以从linux代码中抠过来):

structsockaddr* our_inet_addr(char* cp)

{

char buf[255];

char* p;

int i;

bzero(buf, 255);

if (cp == NULL)

        return NULL;

if (strstr(cp, ":") != NULL)    // IPv6 address

{

        struct sockaddr_in6 * a6 = (structsockaddr_in6*)malloc(sizeof(struct sockaddr_in6));

        memset(a6, 0, sizeof(structsockaddr_in6));

        a6->sin6_family = AF_INET6;

        if (cp[0] == '[')      // If [] exists, strip it off

        {

               p = strstr(cp, "]");

               if (p == NULL)

               {

                      free(a6);

                      return NULL;

               }

               memcpy(buf, cp+1, p-cp-1);

        }

        else

        {

               strcpy(buf, cp);

        }

        if (! inet_pton(AF_INET6, buf,&a6->sin6_addr.s6_addr[0]) )

        {

               free(a6);

               return NULL;

        }

        return (struct sockaddr*)a6;

}

else

{

        struct sockaddr_in* a4 = (structsockaddr_in*)malloc(sizeof(struct sockaddr_in));

        memset(a4, 0, sizeof(structsockaddr_in));

        a4->sin_family = AF_INET;

        if (!inet_pton(AF_INET, cp,&a4->sin_addr.s_addr))

        {

               free(a4);

               return NULL;

        }

        return (struct sockaddr*)a4;

}

}

3.3  groupsockhelper.cpp

函数setupDatagramSocket的定义修改为:

intsetupDatagramSocket(UsageEnvironment& env, Port port, int family=AF_INET);

并在内部在创建socket时将AF_INET修改为动态的family参数。

 

函数setupStreamSocket的定义修改为:

intsetupStreamSocket(UsageEnvironment& env, Port port, BooleanmakeNonBlocking, int family=AF_INET);

并在函数内部做如下修改:

ü        创建socket时将AF_INET修改为动态的family参数

ü        bind所使用的地址,原本由MAKE_SOCKADDR_IN宏来创建,只支持IPv4,改为如下代码来支持IPv6:

       struct sockaddr_in6 addr;

       int addrLen = 0;

       memset(&addr, 0, sizeof(addr));

       if (family == AF_INET)

       {

              ((struct sockaddr_in*)&addr)->sin_family= AF_INET;

              ((structsockaddr_in*)&addr)->sin_port = htons(port.num());

              memcpy(&((structsockaddr_in*)&addr)->sin_addr.s_addr), ReceivingInterfaceAddr, 4);

              addrLen = sizeof(structsockaddr_in);

       }

       else if (family == AF_INET6)

       {

              addr.sin6_family = AF_INET6;

              addr.sin6_port =htons(port.num());

              addr.sin6_flowinfo = 0;

              addr.sin6_scope_id = g_scope_id;

              memcpy(&addr.sin6_addr.s_addr,ReceivingInterfaceAddr, 16);

              addrLen = sizeof(structsockaddr_in6);

       }

if(bind(newSocket, (struct sockaddr*)&addr, addrLen) != 0)

 

函数readSocket的定义修改为:

intreadSocket(UsageEnvironment& env,

             int socket, unsigned char* buffer, unsigned bufferSize,

             struct sockaddr* fromAddress, int* addrsize)

 

函数writeSocket的定义修改为:

BooleanwriteSocket(UsageEnvironment& env,

                 int socket, struct sockaddr* address, Port port,

                 u_int8_t ttlArg,

                 unsigned char* buffer, unsigned bufferSize) {

 

3.4  netaddress.cpp

NetAddressList的构造函数中涉及到对字符串形式的目标地址进行解析并返回一个或多个NetAddress地址。域名解析我们暂不考虑,假定输入的目标地址是IPv4或IPv6形式。

NetAddressList::NetAddressList(charconst* hostname)

  : fNumAddresses(0), fAddressArray(NULL) {

    struct hostent* host;

 

    // Check first whether "hostname"is an IP address string:

    struct sockaddr* addr =our_inet_addr((char*)hostname);

       int addrLen = sizeof(struct sockaddr);

       if (addr->sa_family == AF_INET)

              addrLen = sizeof(structsockaddr_in);

       else if (addr->sa_family == AF_INET6)

              addrLen = sizeof(structsockaddr_in6);

    if (addr != NULL) { // yes it was an IPaddress string

      //##### host =gethostbyaddr((char*)&addr, sizeof (netAddressBits), AF_INET);

      host = NULL; // don't bother callinggethostbyaddr(); we only want 1 addr

      if (host == NULL) {

       // For some unknown reason,gethostbyaddr() failed, so just

       // return a 1-element list with theaddress we were given:

       fNumAddresses = 1;

       fAddressArray = newNetAddress*[fNumAddresses];

       if (fAddressArray == NULL) return;

       fAddressArray[0] = newNetAddress((u_int8_t*)addr, addrLen);

       return;

      }

    } else { // Try resolving"hostname" as a real host name

      host =our_gethostbyname((char*)hostname);

      if (host == NULL) {

       // It was a host name, and we couldn'tresolve it.  We're SOL.

       return;

      }

    }

    u_int8_t const** const hAddrPtr = (u_int8_tconst**)host->h_addr_list;

    if (hAddrPtr != NULL) {

      // First, count the number of addresses:

      u_int8_t const** hAddrPtr1 = hAddrPtr;

      while (*hAddrPtr1 != NULL) {

       ++fNumAddresses;

       ++hAddrPtr1;

      }

      // Next, set up the list:

      fAddressArray = newNetAddress*[fNumAddresses];

      if (fAddressArray == NULL) return;

      for (unsigned i = 0; i <fNumAddresses; ++i) {

       fAddressArray[i] = newNetAddress(hAddrPtr[i], host->h_length);

      }

    }

}

 

以上这些函数接口修改过之后,在整个live555的代码中做如下检查:

ü        搜索代码中的struct sockaddr_in,全部修改为通用的struct sockaddr,并根据sa_family字段来确定实际的地址类型和地址长度

ü        搜索代码中的’AF_INET’,替换为实际的地址类型

ü        搜索代码中的struct in_addr,修改为NetAddress,根据实际地址类型,实际使用struct sin_addr或者struct sin6_addr

以上修改都做完之后,重新编译live555生成库文件。

4  编译liblive555_plugin.dll

第3节重新编译的live555库文件,拷贝到 /win32/lib 下,并将live555 的相关头文件,拷贝到 /win32/include 下,覆盖原来的头文件。

在 modules/demux/live555.cpp 中任意键入一个空格并存盘,更新其修改时间,然后重新编译liblive555_plugin:

cdvlc/modules/demux

make

cd../..

makepackage-win32-base

5  IPv6测试

使用第4节编译生成的vlc,打开AXIS摄像机的IPv6链接:

rtsp://[fe80::240:8cff:fe94:451e]/axis-media/media.amp

即可看到摄像机的画面在VLC中播放出来。

Live555 组播及RTSPClient IPv6改造 扩展Live555 GroupSock及liveMedia,支持rtsp、组播 IPv6播放 阅读详情

相关推荐

基于ffmpeg 监控摄像头 rtsp视频推流 并以opencv播放

在进行视频流项目(视频监控)研发时,通常是在台式机上研发,并不能与摄像头直接进行连接,故需要使用ffmpeg将已经录制好的mp4视频推送为rtsp视频流,然后进行模拟开发。本博文涉及到ffmpeg(推流)、EasyDarwin(视频流服务器)、oepncv(代码拉流)、vlc播放rtsp视频流)。

jason_yuanqing2012的专栏 1540

vlc 8.6可用的最新最全ipv6网络电视列表(2010年12月)

经本人千辛万苦才收集整理好的ipv6网络电视列表,以前在网上流传的好多都是失效的地址,这一百个频道地址经本人全部测试过后均可用,而且是最新可用的,2010年12月还能正常使用ipv6网络电视列表,都是标清的,有少数高清的,非常全面,各高校的ipv6电视资源差不多都收录了,请使用VLC8.6版本,最新版本倒是没有测试是否能用,应该也是能用的,只要地址有效

视频流解码播放VLC

从已有流服务器上接收多媒体流,对码流解码、分析、播放。 站在巨人的肩膀上才能看的更远。对于这个问题,先参考已有的比较成熟的开源项目,从中找到研究的思路。VLC无疑是一个比较好的选择。VLC是一种跨平台的媒体播放器和流媒体服务器。其实VLC开源项目本身就是基于其他的开源项目:FFMPEG,LIVE555.下面主要讲VLC作为多媒体播放器的使用。 引用地址:http://loosky.net/?p

xzdong的专栏 4819

FFmpeg入门详解之6:VLC播放器简介

VLC播放VLC支持多种常见音视频格式,支持多种流媒体传输协议,也可当做本地流媒体服务器使用,功能十分强大。官网下载地址:https://www.videolan.org/VLC多媒体播放器(最初命名为VideoLAN客户端)是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影音光盘及各类流式协议。它也能作为unicast或 multicast的流式服务器在IPv4或 IPv6的高速网络连接下使用。

福优学苑@音视频+流媒体 4517

VLC媒体播放器介绍

VLC媒体播放器介绍VLC媒体播放器是一高度便携的多媒体播放器,可播放多种音视频格式,如:MPEG-1、MPEG-2、MPEG-4、DivX、mp3、ogg等,也支持DVD、VCD和各种流协议。它还能作为在IPv4或IPv6的高带宽网络作为单播或组播流服务器。VLC媒体播放支持Windows、BeOS、Mac OS X、Syllable和各种Linux操作系统。包括:Debian GNU/Lin

chszs的专栏 1万+

VLC安装注意事项及播放RTSP视频流

1前言 2什么是rtsp 3vlc 4如果按照vlc插件 5如何实现rtspvlc播放 6javacv如何实现将rtsp抓图 7avacv如何实现将rtsp录播

指尖上的革新 4141

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

大多数RTSP播放都面向直播场景,如果延迟过大,严重影响体验,所以,低延迟是衡量一个好的RTSP播放器非常重要的指标,目前大牛直播SDK的RTSP直播播放延迟比开源播放器更优异(大牛直播SDK延迟在毫秒级,开源播放器如VLC,延迟相对比较大),而且长时间运行下,大牛直播SDK播放端不会造成延迟累积,开源或第三方播放器,长时间运行,容易产生延迟累积;Google的ExoPlayer是一个开源的媒体播放库,旨在替代Android的MediaPlayer API,并提供了更广泛的格式支持和更好的性能。

大牛直播SDK 6394

【音视频基础】VLC播放

VLC是一款功能强大的开源播放器,VLC的全名为Video Lan Client,是一个开源的、跨平台的视频播放器。VLS支持多种常见音视频格式,支持多种流媒体传输协议,也可当作本地流媒体服务器使用。其官方下载地址为 https://www.videolan.org/。

C/C++Linux、音视频、DPDK 4100

搭建VLC流媒体服务

搭建组播服务器  第一步:运行程序后选择“媒体--串流”; 第二步:通过“添加”选择需要播放的文件(以wmv文件为例),单击“串流”; 第三步:流输出有三项需要设置:来源、目标和选项。来源刚才已指定,点击“下一个”; 第四步:勾选“在本地显示”,选择“RTP/ MPEG Transport Stream”输出,单击“添加”; 第五步:如果建立IPv6组播服务器,可以输

lianghui_zhang的专栏 1973

vlc ipv6网络电视列表

里面有个ipv6.m3u文件,用VLC打开即可 里面还有两个高清台,按理说你找到别的播放列表也是一样的,也是可以播放的,最主要是ipv6的,不担心流量,夜深人静时看球很舒服。 还有些集成好的播放

基于ffmpeg模拟监控摄像头输出rtsp视频流并opencv播放

在进行视频流项目(视频监控)研发时,通常是在台式机上研发,并不能与摄像头直接进行连接,故需要使用ffmpeg将已经录制好的mp4视频推送为rtsp视频流,然后进行模拟开发。本博文涉及到ffmpeg(推流)、EasyDarwin(视频流服务器)、oepncv(代码拉流)、vlc播放rtsp视频流)。

m0_74259636的博客 5201

VLC如何进行RTSP支持(源码阅读心得)

VLC是一个免费,开放源码,跨平台媒体播放器,并集合先进的流媒体功能可以通过IPv4或IPv6的高带宽网络进行流媒体传输。它还支持多种视频格式和流协议。VLC的编解码基于著名的开源项目FFmpeg的libavcodec的开源库。VLC同时提供不同的接口(命令行,网络,图形用户界面,远程登录),以及提供流行的语言如C,C++,C#,Python,和Java可以使用的APIs,这使得VLC变得高度灵活

仲夏夜之梦的博客 4640

Android开发问题集锦八--基于VLCRTSP拉流测评

VLC被很多做视频编解码的小伙伴们熟知,也多用于多媒体播放以及加密DVD影碟等,因为它支持众多音频与视频解码器及文件格式,支持DVD影音光盘,VCD影音光盘及各类流式协议,所以它能作为unicast或multicast的流式服务器在IPv4或IPv6的高速网络连接下使用,它融合了FFmpeg计划的解码器与libdvdcss程序库,故而其优势就更不言而喻了。 作为翘楚的VLC多媒体播放器当然在移动平台也丝毫不逊色,比如手机、平板或电视等,都是主要并且被常用的播放器,“用VLC试试”,这样的口头禅小伙伴们熟悉么

hnjzfwy的博客 2441

【Android组件】---之---VLC视频播放组件

现今Android视频播放组件我知道的有

Alphater 3625

ffmpeg rtsp推流

/ffmpeg -stream_loop -1 -re -i input.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://虚拟机ip:554/live/test0。3、查看gcc版本:根据官网提示,只要这里的gcc版本大于4.8就可以,因为需要支持c++11版本。学习ffmpeg流媒体,需要搭建流媒体服务器,本文用ZLMediaKit搭建rtsp服务器。6、如果端口占用,可以修改配置文件。2、下载组件,网友们都说非常重要。windows vlc拉流。

langzi113的专栏 1364

VLC 服务器RTSP功能实现

<br />http://www.onlyblog.com/blog2/zyjzyj2000/10343.html<br /> <br />主要安装步骤如下:<br />1、安装Fedora7;<br />2、去掉Fedora 7的防火墙,当然也可以自己配置防火墙,允许4212端口和5554端口;<br />3、安装VLC服务器,这个见上面的博客文章;<br />然后配置VLC服务器,配置步骤如下:<br />1、在Fedora 7的控制终端中运行<br />   vlc --ttl 12 -vvv --c

qk_zhu的专栏 3775

F1.10 VLC播放器简介

使用VLC可以很方便地打开网络串流,首先点击主菜单的“媒体”,选择“打开网络串流”(如图3-1所示),然后在弹出的对话框界面中输入“网络URL”(如图3-2所示),点击“播放”按钮,即可看到播放网络流效果(如图3-3所示)。VLC的功能很强大,不仅是一个视频播放器,也可作为小型的视频服务器,还可以一边播放一边转码,把视频流发送到网络上。(5)在该页面点击“添加”按钮,选择具体的流协议,比如RTSP,然后点击“下一个”,(3)点击页面下方的“串流”,添加串流协议,(1)点击主菜单的“流”。

福优学苑@音视频+流媒体 249
ciphor
博客等级 码龄18年 3粉丝 1原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值