龙空技术网

Qt/C++音视频开发56-udp推流和拉流/组播和单播推流

飞扬青云 223

前言:

此刻咱们对“c语言udp组播”大致比较关怀,你们都想要学习一些“c语言udp组播”的相关文章。那么小编同时在网络上搜集了一些有关“c语言udp组播””的相关资讯,希望我们能喜欢,姐妹们一起来了解一下吧!

一、前言

之前已经实现了rtsp/rtmp推流,rtsp/rtmp/hls/flv/ws-flv/webrtc等拉流,这种一般都需要依赖一个独立的流媒体服务程序,有没有一种更便捷的方式不需要这种依赖,然后又能实现推拉流呢,当然有的那就是udpp推流,其中udp推流还可以是组播或者单播推流,组播一般会选择224.0.0.1这个地址,单播的话就是指定到唯一的IP地址比如192.168.0.8,组播的话相当于同一个交换机内所有局域网设备都会收到该数据,优点是推一次所有地方都可以拉流取到数据,缺点是极有可能产生组播风暴,因为每个局域网的设备都可能收到大量的视频数据包,这些完全是多余的。

在之前的ffmpeg推流代码基础上,只需要增加一行代码即可实现udp推流,那就是在调用avformat_alloc_output_context2填入对应的格式需要填入mpegts,其实也可以是h264,但是个人推荐用mpegts,用ffmpeg命令行推流是 ffmpeg -re -stream_loop -1 -i f:/mp4/push/1.mp4 -c copy -f mpegts udp://127.0.0.1:1234 ,可以看到要指定对应的端口号,一个推流占用一个端口号,如果要推10个视频文件就要占用10个端口。

二、效果图三、体验地址国内站点:国际站点:个人作品:体验地址: 提取码:01jf 文件名:bin_video_push。四、功能特点支持各种本地视频文件和网络视频文件。支持各种网络视频流,网络摄像头,协议包括rtsp、rtmp、http。支持将本地摄像头设备推流,可指定分辨率和帧率等。支持将本地桌面推流,可指定屏幕区域和帧率等。自动启动流媒体服务程序,默认mediamtx(原rtsp-simple-server),可选用srs、EasyDarwin、LiveQing、ZLMediaKit等。可实时切换预览视频文件,可切换视频文件播放进度,切换到哪里就推流到哪里。推流的清晰度和质量可调。可动态添加文件、目录、地址。视频文件自动循环推流,如果视频源是视频流,在掉线后会自动重连。网络视频流自动重连,重连成功自动继续推流。网络视频流实时性极高,延迟极低,延迟时间大概在100ms左右。极低CPU占用,4路主码流推流只需要占用0.2%CPU。理论上常规普通PC机器推100路毫无压力,主要性能瓶颈在网络。推流可选推流到rtsp/rtmp两种,推流后的数据支持直接rtsp/rtmp/hls/webrtc四种方式访问,可以直接浏览器打开看实时画面。可以推流到外网服务器,然后通过手机、电脑、平板等设备播放对应的视频流。每个推流都可以手动指定唯一标识符(方便拉流/用户无需记忆复杂的地址),没有指定则按照策略随机生成hash值。自动生成测试网页直接打开播放,可以看到实时效果,自动按照数量对应宫格显示。推流过程中可以在表格中切换对应推流项,实时预览正在推流的视频,并可以切换视频文件的播放进度。音视频同步推流,符合264/265/aac格式的自动原数据推流,不符合的自动转码再推流(会占用一定CPU)。转码策略支持三种,自动处理(符合要求的原数据/不符合的转码),仅限文件(文件类型的转码视频),所有转码。表格中实时显示每一路推流的分辨率和音视频数据状态,灰色表示没有输入流,黑色表示没有输出流,绿色表示原数据推流,红色表示转码后的数据推流。自动重连视频源,自动重连流媒体服务器,保证启动后,推流地址和打开地址都实时重连,只要恢复后立即连上继续采集和推流。提供循环推流示例,一个视频源同时推流到多个流媒体服务器,比如打开一个视频同时推流到抖音/快手/B站等,可以作为录播推流,列表循环,非常方便实用。根据不同的流媒体服务器类型,自动生成对应的rtsp/rtmp/hls/flv/ws-flv/webrtc地址,用户可以直接复制该地址到播放器或者网页中预览查看。编码视频格式可以选择自动处理(源头是264就264/源头是265就265),转H264(强制转264),转H265(强制转265)。支持Qt4/Qt5/Qt6任意版本,支持任意系统(windows/linux/macos/android/嵌入式linux等)。五、相关代码

void FFmpegPushClient::initOsd(){    QList<OsdInfo> osds;    OsdInfo osd;    //日期时间    osd.name = "datetime";    osd.color = "#FFFFFF";    osd.fontSize = 30;    osd.format = OsdFormat_DateTime;    osd.position = OsdPosition_LeftTop;    osds << osd;    //图片    osd.name = "osd.png";    osd.image = QImage(":/image/bg_novideo.png");    osd.format = OsdFormat_Image;    osd.position = OsdPosition_LeftBottom;    //设置唯一名称标识并将图片保存(滤镜基本上都是支持指定图片文件)    osd.name = "osd.png";    QString file = QString("./%1").arg(osd.name);    osd.image.save(file, "png");    osds << osd;    ffmpegThread->setOsdInfo(osds);}void FFmpegPushClient::start(){    if (ffmpegThread || videoUrl.isEmpty() || pushUrl.isEmpty()) {        return;    }    //实例化视频采集线程    ffmpegThread = new FFmpegThread;    //关联播放开始信号用来启动推流    connect(ffmpegThread, SIGNAL(receivePlayStart(int)), this, SLOT(receivePlayStart(int)));    //关联录制信号变化用来判断是否推流成功    connect(ffmpegThread, SIGNAL(recorderStateChanged(RecorderState, QString)), this, SLOT(recorderStateChanged(RecorderState, QString)));    //设置播放地址    ffmpegThread->setVideoUrl(videoUrl);    //设置解码内核    ffmpegThread->setVideoCore(VideoCore_FFmpeg);    //设置视频模式    ffmpegThread->setVideoMode(VideoMode_Opengl);    //设置硬解码(和推流无关/只是为了加速显示/推流只和硬编码有关)    //ffmpegThread->setHardware("dxva2");    //设置解码策略(推流的地址再拉流建议开启最快速度)    //ffmpegThread->setDecodeType(DecodeType_Fastest);    //设置读取超时时间超时后会自动重连    ffmpegThread->setReadTimeout(5 * 1000);    //设置连接超时时间(0表示一直连)    ffmpegThread->setConnectTimeout(0);    //设置重复播放相当于循环推流    ffmpegThread->setPlayRepeat(true);    //设置默认不播放音频(界面上切换到哪一路就开启)    ffmpegThread->setPlayAudio(false);    //设置默认不预览视频(界面上切换到哪一路就开启)    ffmpegThread->setPushPreview(false);    //设置保存视频类将数据包信号发出来用于保存文件    FFmpegSave *saveFile = ffmpegThread->getSaveFile();    saveFile->setSendPacket(!fileName.isEmpty(), false);    connect(saveFile, SIGNAL(receivePacket(AVPacket *)), this, SLOT(receivePacket(AVPacket *)));    connect(saveFile, SIGNAL(receiveSaveStart()), this, SLOT(receiveSaveStart()));    connect(saveFile, SIGNAL(receiveSaveFinsh()), this, SLOT(receiveSaveFinsh()));    connect(saveFile, SIGNAL(receiveSaveError(int)), this, SLOT(receiveSaveError(int)));        //如果是本地设备或者桌面录屏要取出其他参数    VideoHelper::initVideoPara(ffmpegThread, videoUrl, encodeVideoScale);    //设置编码策略/视频编码格式/视频压缩比率/视频缩放比例    ffmpegThread->setEncodeType((EncodeType)encodeType);    ffmpegThread->setVideoFormat((VideoFormat)videoFormat);    ffmpegThread->setEncodeVideoRatio(encodeVideoRatio);    ffmpegThread->setEncodeVideoScale(encodeVideoScale);    //启动播放    ffmpegThread->play();}void FFmpegPushClient::stop(){    //停止推流和采集并彻底释放对象    if (ffmpegThread) {        ffmpegThread->recordStop();        ffmpegThread->stop();        ffmpegThread->deleteLater();        ffmpegThread = NULL;    }    //停止录制    if (ffmpegSave) {        ffmpegSave->stop();        ffmpegSave->deleteLater();        ffmpegSave = NULL;    }}

标签: #c语言udp组播