玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
MultimediaRecord.cpp
1#include <QDesktopServices>
2#include <QUrl>
3#include <QLoggingCategory>
4#include <QDateTime>
5#include <QFileInfo>
6#include "MultimediaRecord.h"
7
8static Q_LOGGING_CATEGORY(log, "WebBrowser.Record")
9
11 : QObject{parent}
12 , m_pMediaDevices(nullptr)
13 , m_VideoFrameStartTime(0)
14{
15 bool check = false;
16 qDebug(log) << Q_FUNC_INFO;
17 if(pPara) {
18 m_ParaRecord = pPara->m_Record;
19 m_pMediaDevices = &pPara->m_MediaDevices;
20 }
21#if HAVE_QT6_RECORD
22 check = connect(&m_Recorder, &QMediaRecorder::recorderStateChanged,
23 this, &CMultimediaRecord::slotRecordStateChanged);
24 Q_ASSERT(check);
25 check = connect(&m_Recorder, &QMediaRecorder::errorOccurred,
26 this, &CMultimediaRecord::slotRecordError);
27 Q_ASSERT(check);
28#endif // #if HAVE_QT6_RECORD
29}
30
31CMultimediaRecord::~CMultimediaRecord()
32{
33 qDebug(log) << Q_FUNC_INFO;
34}
35
36void CMultimediaRecord::slotStart()
37{
38#ifdef HAVE_QT6_RECORD
39 // 配置音频输入(捕获系统音频输入或麦克风)
40 if(m_pMediaDevices) {
41 const auto inputs = QMediaDevices::audioInputs();
42 foreach(auto input, inputs) {
43 if(input.id() == m_pMediaDevices->m_Para.m_AudioInput) {
44 m_AudioInput.setDevice(input);
45 m_CaptureSession.setAudioInput(&m_AudioInput);
46 break;
47 }
48 }
49 }
50 m_CaptureSession.setVideoFrameInput(&m_VideoFrameInput);
51 // 配置录制器, 设置录制参数:输出文件、编码、质量等
52 m_ParaRecord >> m_Recorder;
53 m_CaptureSession.setRecorder(&m_Recorder);
54 m_VideoFrameStartTime = 0;
55 m_Recorder.record();
56#endif
57}
58
59void CMultimediaRecord::slotStop()
60{
61#ifdef HAVE_QT6_RECORD
62 m_Recorder.stop();
63#endif
64 m_pMediaDevices = nullptr;
65}
66
67void CMultimediaRecord::slotUpdateVideoFrame(const QImage image)
68{
69 //qDebug(log) << Q_FUNC_INFO;
70#ifdef HAVE_QT6_RECORD
71 // 将 QImage 转换为 QVideoFrame
72 QImage img = image;
73 //qDebug(log) << "Image format:" << img.format();
74 if(QImage::Format_ARGB32 != image.format())
75 img = image.convertToFormat(QImage::Format_ARGB32);
76 /*
77 QVideoFrameFormat format(image.size(), QVideoFrameFormat::Format_ABGR8888);
78 QVideoFrame frame(format);
79 if (frame.map(QVideoFrame::WriteOnly)) {
80 memcpy(frame.bits(0), image.bits(), image.sizeInBytes());
81 frame.unmap();
82 }//*/
83 QVideoFrame frame(img);
84 // 设置帧的时间戳(微秒),这对于同步很重要
85 if (m_VideoFrameStartTime == 0) m_VideoFrameStartTime = QDateTime::currentMSecsSinceEpoch() * 1000;
86 qint64 currentTime = QDateTime::currentMSecsSinceEpoch() * 1000 - m_VideoFrameStartTime;
87 frame.setStartTime(currentTime);
88 qreal rate = m_ParaRecord.GetVideoFrameRate();
89 if(rate <= 0)
90 rate = 24;
91 frame.setEndTime(currentTime + qreal(1000000) / rate);
92 frame.setStreamFrameRate(m_ParaRecord.GetVideoFrameRate());//*/
93 m_VideoFrameInput.sendVideoFrame(frame);
94#endif
95}
96
97#if HAVE_QT6_RECORD
98void CMultimediaRecord::slotRecordStateChanged(QMediaRecorder::RecorderState state)
99{
100 qDebug(log) << "Record state:" << state;
101 switch(state) {
102 case QMediaRecorder::RecorderState::StoppedState: {
103 QString szFile = m_Recorder.actualLocation().toLocalFile();
104 switch(m_ParaRecord.GetEndAction())
105 {
106 case CParameterRecord::ENDACTION::OpenFile: {
107 bool bRet = QDesktopServices::openUrl(QUrl::fromLocalFile(szFile));
108 if(!bRet)
109 qCritical(log) << "Fail: Open capture page the file:" << szFile;
110 break;
111 }
112 case CParameterRecord::ENDACTION::OpenFolder: {
113 QFileInfo fi(szFile);
114 QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath()));
115 break;
116 }
117 default:
118 break;
119 }
120 emit sigFinished();
121 break;
122
123 }
124 case QMediaRecorder::RecorderState::RecordingState: {
125 emit sigRunning();
126 break;
127 }
128 default:
129 break;
130 }
131}
132
133void CMultimediaRecord::slotRecordError(QMediaRecorder::Error error, const QString &errorString)
134{
135 qCritical(log) << error << errorString;
136 emit sigFinished();
137}
138#endif // HAVE_QT6_RECORD
139
140CMultimediaRecordThread::CMultimediaRecordThread(
141 CParameterWebBrowser* pPara, QObject *parent)
142 : QThread(parent)
143 , m_pPara(pPara)
144 , m_pRecord(nullptr)
145{
146 qDebug(log) << Q_FUNC_INFO;
147 connect(this, &QThread::finished, this, &QObject::deleteLater);
148}
149
150CMultimediaRecordThread::~CMultimediaRecordThread()
151{
152 qDebug(log) << Q_FUNC_INFO;
153}
154
155void CMultimediaRecordThread::run()
156{
157 m_pRecord = new CMultimediaRecord(m_pPara);
158 if(!m_pRecord) return;
159 connect(m_pRecord, &CMultimediaRecord::sigFinished,
160 this, &QThread::quit);
161 m_pRecord->slotStart();
162 exec();
163 delete m_pRecord;
164 m_pRecord = nullptr;
165}
166
167void CMultimediaRecordThread::slotUpdateVideoFrame(const QImage image)
168{
169 if(!m_pRecord) return;
170 m_pRecord->slotUpdateVideoFrame(image);
171}
172
173void CMultimediaRecordThread::slotQuit()
174{
175 if(!m_pRecord) return;
176 m_pRecord->slotStop();
177 /*
178 QMetaObject::invokeMethod(m_pRecord,
179 "slotStop",
180 Qt::AutoConnection);*/
181}