一、前言
之前已经实现了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个端口。
二、效果图
三、体验地址
四、功能特点
五、相关代码
void FFmpegPushClient::initOsd()
{
QList osds;
OsdInfo osd;
//日期时间
osd.name = "datetime";
osd.color = "#FFFFFF";
osd.fontSize = 30;
osd.format = OsdFormat_DateTime;
osd.position = OsdPosition_LeftTop;
osds 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;
}
}