ffmpeg本地图片(摄像头)推rtmp流

方法原理

此部分包括三部分:ffmpeg推流、web服务器(nginx)、videojs拉流/Vlc播放器。

ffmpeg

  • ffmpeg加入编码器选项(libx264)
  • ffmpeg编译程序时注意版本兼容问题以及链接库的顺序问题

nginx服务器搭建

  • .安装gcc g++依赖库
    sudo apt-get install build-essential
    sudo apt-get install libtool
  • 安装pcre依赖库
    sudo apt-get update
    sudo apt-get install libpcre3 libpcre3-dev
  • .安装zlib依赖库
    sudo apt-get install zlib1g-dev
  • 安装SSL依赖库
    sudo apt-get install openssl libssl-dev
  • 安装NGINX
    #下载NGINX(到HOME目录)
    wget http://nginx.org/download/nginx-1.13.10.tar.gz
    #解压
    tar -zxvf nginx-1.13.10.tar.gz
    #下载RTMP(到HOME目录)
    git clone https://github.com/arut/nginx-rtmp-module.git
    #进入NGINX解压目录
    cd nginx-1.13.10
    #配置
    ./configure --prefix=/usr/local/nginx --add-module=~/nginx-rtmp-module --with-http_ssl_module
    #编译
    make
    #安装
    sudo make install
    #打开nginx配置文件
    cd /usr/local/nginx/conf/
    sudo gedit nginx.conf
    #下拉至文档末尾,添加RTMP服务
    rtmp {
    server {
    listen 2018; #服务端口,避开重要端口即可
    application live {
    live on;
    }
    application hls_alic{
    live on;
    hls on;
    hls_path /tmp/hls;
    }
    }
    #不要关闭文档,回到http服务配置处,按以下样式对其修改,最后保存并退出
    http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    server {
    listen 80;
    server_name localhost;
    location /stat {
    rtmp_stat all;
    rtmp_stat_stylesheet stat.xsl;
    }
    location /stat.xsl {
    root /usr/local/nginx/nginx-rtmp-module/;
    }
    location / {
    root html;
    index index.html index.htm;
    }
    error_page 404 /404.html
    location = /50x.html {
    root html;
    }
    }
    }
    #开启nginx服务
    cd /usr/local/nginx/sbin
    sudo ./nginx
    #如要查看NGINX服务是否开启,请打开浏览器并输入localhost,如果看到nginx页面即为成功,或使用以下代码
    ps -ef|grep nginx

videojs/vlc拉流

  • vlc自行百度下载,打开网络串流即可
  • videojs播放,关键html代码截图如下,利用插件flash播放

在这里插入图片描述

ffmpeg本地推流部分关键代码

//nginx-rtmp 直播服务器rtmp推流URL
    char *outUrl = "rtmp://192.168.3.105:2019/live";
    //注册所有的编解码器
    avcodec_register_all();
    //注册所有的封装器
    av_register_all();
    //注册所有网络协议
    avformat_network_init();
	VideoCapture cam;
    Mat frame;
    //像素格式转换上下文
    SwsContext *vsc = NULL;
    //输出的数据结构
    AVFrame *yuv = NULL;
    //编码器上下文
    AVCodecContext *vc = NULL;
    //rtmp flv 封装器                                                           
    AVFormatContext *ic = NULL;
    /// 1 使用opencv打开rtsp相机
    cam.open(0); // 本地相机
	if (!cam.isOpened())
    {
            cout<<"camera is not open<<endl;";
    }
            if (!cam.grab())
            {
                continue;
            }
            ///yuv转换为rgb
            if (!cam.retrieve(frame))
            {
                continue;
            }
            waitKey(20);
gettimeofday(&endtime1,NULL);
				double timeuse1 = endtime1.tv_sec - starttime1.tv_sec + (endtime1.tv_usec - starttime1.tv_usec)/(double)1000000; 
cout<<"cap:"<<timeuse1<<endl;
            ///rgb to yuv
            //输入的数据结构
            uint8_t *indata[AV_NUM_DATA_POINTERS] = { 0 };
            indata[0] = frame.data;
            int insize[AV_NUM_DATA_POINTERS] = { 0 };
            //一行(宽)数据的字节数
            insize[0] = frame.cols * frame.elemSize();
            int h = sws_scale(vsc, indata, insize, 0, frame.rows, //源数据
                yuv->data, yuv->linesize);
            if (h <= 0)
            {
                continue;
            }
            ///h264编码
            yuv->pts = vpts;
            vpts++;
			int got_picture=0;
			avcodec_encode_video2(vc,&pack,yuv,&got_picture);
            if (ret != 0 || pack.size > 0)
            {
                cout << "*" << pack.size << flush;
            }
            else
            {
                cout<<"continue";
				continue;
            }
            //推流
            pack.pts = av_rescale_q(pack.pts, vc->time_base, vs->time_base);
            pack.dts = av_rescale_q(pack.dts, vc->time_base, vs->time_base);
            pack.duration = av_rescale_q(pack.duration, vc->time_base, vs->time_base);
            ret = av_interleaved_write_frame(ic, &pack);
            if (ret == 0)
            {
                cout << "#" << flush;
            }
			cout<<"okokokokok"<<endl;
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值