• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

树莓派高清视频直播服务器

snowstorm 2014-07-05 浏览量:12405

项目描述:摄像机拍摄1080p高清视频,编码成h.264格式后,通过网线传输给路由器,客户端通过rtsp地址观看视频

暂定方案:高清视频经FPGA编码成h.264格式,传给树莓派,树莓派将h264码流通过网线传输给路由器

问题:刚接触树莓派,不知树莓派编程方面如何下手,需要学哪些东西,求大神给个指导性的建议~

ps:该方案不知是否可行,希望大家也提点建议~

                   

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案

其他答案 数量:42
  • live555官方源码下到ubuntu里,输入:

    tar xvf live555-latest.tar.gz
    cd live

    ./genMakefiles linux

    make

    产生的可执行文件在ubuntu里均能够无误运行

    • 发布于2014-08-03
    • 举报
    • 评论 0
    • 0
    • 0

  • 新进展,真是一波三折

    感谢鱼总和各位朋友的帮助,在百忙之中帮我分析问题,有了你们论坛才有源头活水。先感慨一下,这个论坛的版主很负责,有些论坛基本问了就没人回答,毕竟这是双向的,论坛帮助了我们,我们才会更好的反馈,比如这个项目要是完工了,发帖全程记录下来,为更多的朋友提供参考,这样论坛才是活的嘛。下面报告调试记录:

    之前live555是这样编译的

    ./genMakefiles linux

    make

    现在把config.armlinux文件的

    CROSS COMPILE? = arm-elf   改成

    CROSS COMPILE? = arm-linux    

    终端输入:

    ./genMakefiles armlinux

    make

    这样live555的库就是arm版本的了,上述问题没了,出现如下问题:


    我尝试着写了makefile,上面截图是运行make产生的,makefile文件贴在下面:

    ###################################Makefile####################################

    LIVE555= ..
    CXX = arm-linux-g++
    CC = arm-linux-gcc
    all: ccl 

    LIB_SUFFIX=a
    INCLUDES = -I$(LIVE555)/UsageEnvironment/include -I$(LIVE555)/groupsock/include
      -I$(LIVE555)/liveMedia/include -I$(LIVE555)/BasicUsageEnvironment/include
    CXXFLAGS= -c -fPIC $(INCLUDES)

    USAGE_ENVIRONMENT_DIR = $(LIVE555)/UsageEnvironment
    USAGE_ENVIRONMENT_LIB = $(USAGE_ENVIRONMENT_DIR)/libUsageEnvironment.$(LIB_SUFFIX)
    BASIC_USAGE_ENVIRONMENT_DIR = $(LIVE555)/BasicUsageEnvironment
    BASIC_USAGE_ENVIRONMENT_LIB = $(BASIC_USAGE_ENVIRONMENT_DIR)/libBasicUsageEnvironment.$(LIB_SUFFIX)
    LIVEMEDIA_DIR = $(LIVE555)/liveMedia
    LIVEMEDIA_LIB = $(LIVEMEDIA_DIR)/libliveMedia.$(LIB_SUFFIX)
    GROUPSOCK_DIR = $(LIVE555)/groupsock
    GROUPSOCK_LIB = $(GROUPSOCK_DIR)/libgroupsock.$(LIB_SUFFIX)
    LOCAL_LIBS = $(LIVEMEDIA_LIB) $(GROUPSOCK_LIB)
    $(BASIC_USAGE_ENVIRONMENT_LIB) $(USAGE_ENVIRONMENT_LIB)

    ccl: ccl.o capture.o compress.o SsbSipMfcEncAPI.o $(LOCAL_LIBS)
    $(CC) -o $@ $^ -fPIC  -L/usr/local/lib -lpthread -lstdc++

    SsbSipMfcEncAPI.o:SsbSipMfcEncAPI.c
    $(CC) $(CXXFLAGS) $<

    compress.o:compress.c
    $(CC) $(CXXFLAGS) $<

    capture.o:capture.cpp
    $(CXX) $(CXXFLAGS) $<

    ccl.o:ccl.cpp 
    $(CXX) $(CXXFLAGS) $<

    clean:
    rm  *.o
    rm  ccl

    #######################################END#######################################
    从截图的错误看出ccl.cpp里没有定义vc_open(),vc_compress(),vc_close()这三个函数,但我include了compress.h  如下:

    extern "C" {
      #include "compress.h"
    }
    因为compress.c是个c文件,ccl.cpp是个c++文件,c++调用c函数,要加extern "C" 

    为什么会undefined reference??

    这三个函数是在ccl.cpp里一个class的成员函数里调用的,但成员函数也调用了capture.cpp里的函数,确没报错~~。。~~

    对了,有一点,我后来把

    extern "C" {
      #include "compress.h"
    }

    直接改成

    extern "C" {
        void *vc_open (int width, int height, int fps);
        int vc_close (void *ctx_t);
        int vc_compress (void *ctx_t,Picture *pic);

    }

    报错如下:


    意思好像是说,这三个函数之前用C++ linkage定义的,后来又用C linkage来定义,这就冲突了,我就哭了

    在makefile里明明是用CC编译的,搞不懂了


    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 唉,说实话,C,C++这块我也不是很懂。

    帮你乱分析一下吧:compress.c中有没有这三个函数,compress.c是不是放到了和compress.h同一个文件夹?

    通过搜索得知,还可以预处理一下C的头文件。比如通过以下方式:

    a.h:

    #ifndef __A_H
    #define __A_H

    #ifdef __cplusplus
    extern "C" {
    #endif

    int ThisIsTest(int a, int b);

    #ifdef __cplusplus
    }
    #endif

    #endif

    这样处理C的头文件后直接在Cpp里调用就可以了。

    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 这得直接大召唤C++大牛。。。。。我去喊 一下。

    这个工程直接在arm设备上编译试过吗?

    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • V4L?为啥不用V4L2?linux 2.6之后就有了。还有。你这似乎是调用的库间接调用V4L?
    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 是V4L2啊,capture.cpp定义了三个函数,全是V4L2相关的


    void *capture_open (const char *dev_name, int t_width, int t_height)    //打开v4l2设备

    int capture_get_picture(void *id, Picture *pic)    //获得一帧图片,nv12格式

    int capture_close (void *id)    //关闭v4l2设备


    直接贴代码看不清,代码跟注释都一个颜色,为了方便看代码,换一楼贴

    这三个函数见下一楼,30楼

    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 在虚拟机上编译的,产生一个可执行文件ccl  ,拷到arm上直接运行

    没有在arm上编译,arm上连gcc都没有,不好编译

    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 我是不是又发现个论坛bug?

    上面代码有半边没了。。。给跪

    直接传文件吧,整个工程都在里面

    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 发的贴子不能包含E_X_E_C这个Word。不是BUG,最近审查严格
    • 发布于2014-08-04
    • 举报
    • 评论 0
    • 0
    • 0

  • 召唤会live555的最好了,最新进展已直播,问题仍然处在live555上
    • 发布于2014-08-05
    • 举报
    • 评论 0
    • 0
    • 0

  • 关于Live555 的编译,live555在树莓派上直接编译通过呢

    跨平台交叉编译,你是用的树莓派官方的交叉编译工具吗?

    我在树莓派上是这么编译的

    #把config.armlinux文件的
    CROSS COMPILE?= arm-elf   改成
    CROSS COMPILE?= ""
    #然后
    ./genMakefiles armlinux
    make
    编译通过了,或者你可以把那个交叉编译工具指向树莓派Github上的官方的交叉编译工具试试。

    关于H264的Profile和Level

    这儿有篇文章详解:http://xcshen.blog.51cto.com/2835389/552669

    这是里边的图,你把00000替换成相应的数字试试呢?

    • 发布于2014-08-06
    • 举报
    • 评论 0
    • 0
    • 0

  • 当你看到这段文字时,你无法理解此刻楼主的心情,现在0:42分,重大突破,也许你觉得楼主很傻X,这破玩意你可能几年前就弄出来了,但对于楼楼这样一个小白。。。。而且今天卡了一天了,临睡前惊喜地看到画面了,再说都要哭出来了,直接上图:

    马赛克严重,静态景物比较清晰,动态时就更加严重,下图为证:

    大约过了10+秒,自己恢复了,见下图

    这张比较清晰,当画面程静态时,就会逐渐变清晰,这种自我修复的功能源于264编码特性


    恢复时长应该跟I帧周期有很大关系吧


    都好几天了,一直不出画面,今天意外惊喜

    兴奋的都睡不着了,明天开始调参数

    时候不早了,简单说一下原因:


    mfc编码初始化之后,要获取header,我存到文件里了,但没有送给live555,只是把每一帧编码数据送给live555,但这个header至关重要,他包


    含了视频文件的帧率、sps、spp、扩展信息,没有这些信息是无法解码的,这就是为什么pc显示时间进度条确没有画面出现。


    当然,我上午就加了header,还是不出画面,真实坎坷啊。。。。


    加了header后,播放几帧获取SDPLine后,有一个类直接析构了,然后整个程序崩溃,出现Segmentation fault段错误,没在意,一直在找析构的


    原因,一直在看live的代码,陷入了在live555的代码中,浪费了不少时间


    无意间又看了看自己的代码,大概知道那个段错误的原因了,因为以前也遇到过,就是为一个指针申请了内存空间malloc(),却忘了释放空间


    free(),导致内存泄漏,我只是为了消除哪个段错误,睡前至少解决一个小bug,不然今天一点进展没有,没想到意外就发生了,就有画面了


    延时1~2秒


    其实后面的事还有挺多,调参数,增大画面,改善延时,移植底层视频驱动,估计逃不了加声音。。。


    关于mfc编码参数,我的压缩比已经达到惊人的400+,原来一帧115200字节,编码后100不到,有的甚至才12字节,画


    质好就怪了。所以希望大家给点参考,我不要那么高的压缩比,我要画质!


    另外怎么加音频,是另加一路音频编码还是直接传输mpg格式,这个格式好像自带音视频;如果另加一路音频,那么音视频如何同步,live555能


    做到音视频两路同时直播吗,是否涉及多线程,所以问题还很多,


    希望接触过这个的朋友们一起讨论~~


    在此特别感谢 咕唧咕唧的帮助    http://blog.csdn.net/liukun321/article/details/24390379 

    不然我也不会想到加header

    • 发布于2014-08-07
    • 举报
    • 评论 0
    • 0
    • 0

  • 谢谢鱼总,我后来发现那个函数治标不治本,还是得让程序自己去获得sdp,不然换个设备可能就出问题了


    所以我把函数注释掉了,rtsp传输加了header,详见40楼

    • 发布于2014-08-07
    • 举报
    • 评论 0
    • 0
    • 0

  • 最新进展:

    分辨率由原来320*240增加到640*480

    流畅播放,但有延时约2秒不到,说明代码还得优化

    马赛克消除,画质改善,但仍不是很清晰

    两台笔记本可同时观看,说明组播已实现

    ipad也可观看,手机不行,卡死,说明手机该换了


    更正一下,上次出画面完全是偶然,因为第二天又不出画面了,全过程如下:

    arm打印信息如下:


    [1301] WebcamOndemandMediaSubsession .... calling

    using url "rtsp://192.168.253.209:8554/webcam"

    [1301] createNewStreamSource .... calling

    [1301] WebcamFrameSource .... calling

    Current input name: ov9650

     field =1

     nv12 fmt!

    capture_open: using MEMORY_MMAP mode, buf cnt=1

    ImageSize[0] = 115200

    support RGB-5-6-5

    support RGB-8-8-8, unpacked 24 bpp

    support YUV 4:2:2 packed, YCbYCr

    support YUV 4:2:2 packed, CbYCrY

    support YUV 4:2:2 packed, CrYCbY

    support YUV 4:2:2 packed, YCrYCb

    support YUV 4:2:2 planar, Y/Cb/Cr

    support YUV 4:2:0 planar, Y/CbCr

    support YUV 4:2:0 planar, Y/CbCr, Tiled

    support YUV 4:2:0 planar, Y/CrCb

    support YUV 4:2:2 planar, Y/CbCr

    support YUV 4:2:2 planar, Y/CrCb

    support YUV 4:2:0 planar, Y/Cb/Cr

    support Encoded JPEG bitstream

    support

    support

    Open Device OK!

    StartStream OK!

    MfcEncOpen succeeded

    SsbSipMfcEncInit: Encode Init start

    SsbSipMfcEncInit: H264 Encode

    SsbSipMfcEncInit succeeded

    SsbSipMfcEncGetOutBuf suceeded

    headersize= 22

    head=

    SsbSipMfcEncGetInBuf succeeded

    [1301] createNewRTPSink .... calling

    [1301] getAuxSDPLine .... calling

    startPlaying

    [1301] chkForAuxSDPLine1 .... calling

    after getting AuxSDPLine

    [1301] getNextFrame1 .... call

    capture_get_picture: DQ index=0

    fFrameSize=22772  fMaxSize=150000

    [1301] getNextFrame1 .... call

    capture_get_picture: DQ index=0

    fFrameSize=3781  fMaxSize=127228

    [1301] getNextFrame1 .... call

    capture_get_picture: DQ index=0

    fFrameSize=21  fMaxSize=123447

    [1301] getNextFrame1 .... call

    capture_get_picture: DQ index=0

    fFrameSize=12  fMaxSize=123426

    [1301] getNextFrame1 .... call

    capture_get_picture: DQ index=0

    fFrameSize=12  fMaxSize=123414

    [1301] chkForAuxSDPLine1 .... calling

    chkForAuxSDPLine1 success !

    after doEventLoop

    getAuxSDPLine return mp_sdp_line= a=fmtp:96 packetization-mode=1;profile-level-id=640028;sprop-parameter-sets=Z2QAKKzTBQfk,aOpAbywAAAAAAAAAAAAAAA……(此处省略几千个A)

    [1301] ~WebcamFrameSource .... calling

    SsbSipMfcEncClose Success!

    Segmentation fault 



    最后一个段错误上次通过释放header指针解决了,

    但倒数第三句还在,就是析构了,然后终中断,pc看不到画面

    同时从上面的几千个A看出,pps提取出错,sps倒是正确的

    于是开始痛苦地研究live关于pps的代码,主要看    源码 + live官网 + http://blog.csdn.net/gavinr


    这篇博客让人思路清晰

    live官网提供所有文件、函数、class等等的查询,可以快速查找你想要找的函数,因为live的整个架构很复杂,

    我一开始可能看一个代码花20分钟,找一个函数花半小时。。。


    live555源码分析---- DESCRIBE命令处理  关于sps、pps在这篇文章里


    大致流程就是:


    void RTSPServer::RTSPClientSession  ::handleCmd_DESCRIBE   处理DESCRIBE,其中调用下面的函数

    sdpDescription = session->generateSDPDescription();               获得SDP,SDP大部分都好获取,

                                                                                        但媒体描述部分不太容易获取,这部分要调用下面的函数

    subsession->sdpLines()                                                      这个函数定义在ServerMediaSubsession中的纯虚函数,在                数在       OnDemandServerMediaSubsession::sdpLines()中实现,实现过程为三步走:


    第一步:实例化source

    第二步:实例化RTPSink

    第三步:调用下面的函数获取媒体部分的SDP,前两部是为第三步服务,因为这个函数的参数是前两个实例


    void OnDemandServerMediaSubsession  ::setSDPLinesFromRTPSink

    媒体相关的描述大部分都好办,就是有一个可选的扩展属性,需要调用下面的函数获取

    auxSDPLine()  这个函数是父类RTPSink的成员函数,返回空,需要在子类H264VideoRTPSink中重实现,如下:


    H264VideoRTPSink::auxSDPLine()    此函数中调用下面的函数获得sps和pps

    framerSource->getSPSandPPS(sps, spsSize, pps, ppsSize); 注意,这是老版本的live,在新版本中就这个函数改了个名

    getVPSandSPSandPPS   


    新版本做了一些优化,但大差不差


    这个函数getVPSandSPSandPPS  在哪?博主没有继续分析,我就自己找了,

    此函数中就三行:
    vps = fLastSeenVPS; vpsSize = fLastSeenVPSSize;
    sps = fLastSeenSPS; spsSize = fLastSeenSPSSize;
    pps = fLastSeenPPS; ppsSize = fLastSeenPPSSize;
    fLastSeenPPSSize 哪来?下面来 :
    void H264or5VideoStreamFramer::saveCopyOfPPS(u_int8_t* from, unsigned size)
     {
      if (from == NULL) return;

      delete[] fLastSeenPPS;
     
     fLastSeenPPS = new u_int8_t[size];
     
     memmove(fLastSeenPPS, from, size);

     
     fLastSeenPPSSize = size;

     }


    saveCopyOfPPS这个函数定义及调用均在这个文件里: H264or5VideoStreamFramer.cpp


    调用:usingSource()->saveCopyOfPPS(fStartOfFrame + fOutputStartCodeSize, curFrameSize() - fOutputStartCodeSize);


    其中fOutputStartCodeSize = 0   curFrameSize()竟然 = 7000


    这就是为什么arm打印了几千个A,因为从源头上获取的pps的size就这么大,


    当然正常情况下pps就几个字节,不会有7000的,所以:

    要么是提取pps的算法有问题,

    要么我传给live555的数据源本身就有问题


    估计是数据源的问题,因为live555毕竟是公司做的软件

    而且直播264文件没问题


    数据源怎么有问题现在不知道!!!!!!!!!


    我暂时只能这样处理:


    加上一句:若size大于20,则让他等于20


    毕竟动态分配20大小的空间要比分配7000要好


    目前pc都能出画面了,但治标不治本,还是存在bug,问题没有从根本解决


    另外说一下,最先送给live555的不是264的head,而是解码后的数据,


    先送5帧编码后的数据,在这期间arm无法获取head ,   pc没有画面,


    然后吧head送给live555,他就获取head了,pc慢慢就有画面了


    也不一定非要十几帧,两三帧甚至直接给head都有可能行,我还没试


    稍微总结一下:sps和pps属于   SDP的媒体相关部分   中的    可扩展属性   的一部分


    最后再说一下怎么调试


    我没用过  gdb  也不会用  也不想用


    就在程序里加入很多打印信息函数fprintf(),可以有效跟踪程序的走向


    对于一般的代码,这么调试足够了


    对于live555  ,就比较困难了,很容易跟丢了


    好在live提供DEBUG,就是在文件里宏定义DEBUG


    就能输出很多打印信息


    后面的工作:


    看看我的264文件,数据源有什么问题,跟标准264文件对比一下

    改善画质

    串口终端怎么用









    • 发布于2014-08-09
    • 举报
    • 评论 0
    • 0
    • 0

  • 笔误:解码改成编码就对了

    截图后面有空再传,估计画质改善不到哪去

    100块的cmos摄像头,用官方代码跑出来的画质都不敢恭维

    • 发布于2014-08-09
    • 举报
    • 评论 0
    • 0
    • 0

  • 前段时间把画质稍微改善了一下,主要是调高码率,

    摄像头不太给力,画质就这水平了,600*800, 25fps ,延时0.8秒,流畅


    官方摄像头最高就600*800,


    所以现在考虑将摄像头输入换成HDMI输入


    arm板都是HDMI输出,从来没有输入的,


    所以用hdmi视频芯片adv7611,其作用是将hdmi输入信号分流为视频跟音频两路信号,


    视频信号通过camera接口连接核心板,原来的摄像头也是通过camera接口连接的核心板


    视频芯片跟核心板已经画在一个板子上了,所以最终的成品就是一个板子,加两根线:hdmi输入线、网线作为输出


    问题:之前只是会用v4l2的应用层函数,现在要将芯片驱动跟v4l2对接


           这就要对v4l2底层驱动比较熟悉,有个问题:


           应用层函数ioctl(fd,VIDIOC_S_FMT,&stream_fmt)   具体是在哪个文件里定义的?

    • 发布于2014-08-23
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

树莓派高清视频直播服务器