一、基本介紹
該軟件裏推流和視頻保存使用FFMPEG庫完成,視頻和音頻可以同步推流和錄製,FFMPEG本身支持跨平臺編譯開發,QT也支持跨平臺,在Android、Linux、windows都運行良好,只需要在不同平臺編譯對應的ffmpeg庫即可,邏輯代碼部分通用。
由於核心代碼和在發表博客裏的代碼差不多這裏就不再貼出代碼。
FFMPEG編程使用參考的鏈接:
(1) 使用NDKR19C編譯最新的FFMPEG和X264給Android平臺使用:https://blog.csdn.net/xiaolong1126626497/article/details/104734472
(2) linux下使用QT調用FFMPEG讀取攝像頭一幀數據顯示到標籤控件上
https://blog.csdn.net/xiaolong1126626497/article/details/104719820
(3) QT在Android設備上實現FFMPEG開發: 完成拍照、MP4視頻錄製、rtsp推流
https://blog.csdn.net/xiaolong1126626497/article/details/104760149
(4) QT獲取Android、Linux、Windows系統上的攝像頭數據幀與聲卡音頻通過FFMPEG編碼爲MP4存儲(v1.0)
https://blog.csdn.net/xiaolong1126626497/article/details/104858499
(5) QT採集攝像頭數據幀與聲卡音頻通過FFMPEG實時推流到RTMP服務器(v1.0)
https://blog.csdn.net/xiaolong1126626497/article/details/104866323
二、windows下軟件運行效果
(1)主界面效果
(2)保存視頻到本地,設置錄製間隔爲10秒一個視頻
(3)推流視頻到B站,必須保證RTMP地址是有效的,如果地址無效軟件會自動退出
三、核心代碼
代碼裏除了FFMEG代碼之外,主要的核心代碼是攝像頭顏色轉換代碼,因爲不同的攝像頭輸出的原始格式不一樣,代碼裏還需要做顏色轉換。
void VideoReadThread_0::slotOnProbeFrame(const QVideoFrame &frame)
{
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
// qDebug()<<"height:"<<cloneFrame.height();
// qDebug()<<"width:"<<cloneFrame.width();
//qDebug()<<"bytesPerLine:"<<cloneFrame.bytesPerLine();
//qDebug()<<"mappedBytes:"<<cloneFrame.mappedBytes();
//qDebug()<<"pixelFormat:"<<cloneFrame.pixelFormat();
unsigned char rgb_buffer[VIDEO_WIDTH*VIDEO_HEIGHT*3];
if(cloneFrame.pixelFormat()==QVideoFrame::Format_NV21)
{
NV21_TO_RGB24(cloneFrame.bits(),rgb_buffer,cloneFrame.width(),cloneFrame.height());
}
else if(cloneFrame.pixelFormat()==QVideoFrame::Format_YUYV)
{
yuyv_to_rgb(cloneFrame.bits(),rgb_buffer,cloneFrame.width(),cloneFrame.height());
}
else if(cloneFrame.pixelFormat()==QVideoFrame::Format_RGB24)
{
memcpy(rgb_buffer,cloneFrame.bits(),sizeof(rgb_buffer));
}
else if(cloneFrame.pixelFormat()==QVideoFrame::Format_BGR24)
{
memcpy(rgb_buffer,cloneFrame.bits(),sizeof(rgb_buffer));
}
else if(cloneFrame.pixelFormat()==QVideoFrame::Format_Jpeg)
{
}
else
{
qDebug("當前格式編碼爲%1,暫時不支持轉換.\n");
}
//加載圖片數據
QImage image(rgb_buffer,
cloneFrame.width(),
cloneFrame.height(),
QImage::Format_RGB888);
if(cloneFrame.pixelFormat()==QVideoFrame::Format_BGR24)
{
image=image.rgbSwapped(); //BGR格式轉RGB
image=image.mirrored(false, true);
}
if(cloneFrame.pixelFormat()==QVideoFrame::Format_Jpeg)
{
image.loadFromData((const uchar *)cloneFrame.bits(),cloneFrame.mappedBytes());
}
//繪製圖片水印
QDateTime dateTime(QDateTime::currentDateTime());
//時間效果: 2020-03-05 16:25::04 週一
QString qStr="";
qStr+=dateTime.toString("yyyy-MM-dd hh:mm:ss ddd");
QPainter pp(&image);
QPen pen = QPen(Qt::white);
pp.setPen(pen);
pp.drawText(QPointF(0,20),qStr);
//提取RGB數據
unsigned char *p=rgb_buffer;
for(int i=0;i<image.height();i++)
{
for(int j=0;j<image.width();j++)
{
QRgb rgb=image.pixel(j,i);
*p++=qRed(rgb);
*p++=qGreen(rgb);
*p++=qBlue(rgb);
}
}
videoaudioencode_0.video_encode_mutex.lock();
RGB24_TO_YUV420(rgb_buffer,image.width(),image.height(),video_yuv420p_buff);
videoaudioencode_0.video_encode_mutex.unlock();
videoaudioencode_0.video_WaitConditon.wakeAll();
emit VideoDataOutput(image); //發送信號
cloneFrame.unmap();
}
xxx.pro工程文件代碼:
QT += core gui
QT += multimediawidgets
QT += xml
QT += multimedia
QT += network
QT += widgets
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
Color_conversion.cpp \
audio_video_encode_0.cpp \
ffmpeg_code.cpp \
main.cpp \
widget.cpp
HEADERS += \
Color_conversion.h \
audio_video_encode_0.h \
config.h \
ffmpeg_code.h \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RC_ICONS=log.ico
win32
{
message('運行win32版本')
INCLUDEPATH+=$$PWD/ffmpeg-win32-shared-dll/include
LIBS+=$$PWD/ffmpeg-win32-shared-dll/bin/av*
LIBS+=$$PWD/ffmpeg-win32-shared-dll/bin/sw*
LIBS+=$$PWD/ffmpeg-win32-shared-dll/bin/pos*
}
RESOURCES += \
image.qrc
四、軟件和FFMEG庫下載地址
第一版下載地址(沒有支持輸出JPEG和RGB24的攝像頭): https://download.csdn.net/download/xiaolong1126626497/12304729
第二版下載地址(支持輸出JPEG、RGB24、YUYV、NV21、BGR24源數據的攝像頭):https://download.csdn.net/download/xiaolong1126626497/12304904
下面公衆號有全套QT\C\C++\單片機基礎教程,歡迎關注: