欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-04 23:28:10
...

方法原理

此部分包括三部分: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本地图片(摄像头)推rtmp流

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;
相关标签: c++ ffmpeg